Don't remove all locals to external assemblies
This commit is contained in:
parent
686f9953fd
commit
e2f3fd259d
|
@ -123,13 +123,38 @@ namespace de4dot.blocks {
|
||||||
|
|
||||||
int newIndex = -1;
|
int newIndex = -1;
|
||||||
var newLocals = new List<Local>(usedLocals.Count);
|
var newLocals = new List<Local>(usedLocals.Count);
|
||||||
|
var newLocalsDict = new Dictionary<Local, bool>(usedLocals.Count);
|
||||||
foreach (var local in usedLocals.Keys) {
|
foreach (var local in usedLocals.Keys) {
|
||||||
newIndex++;
|
newIndex++;
|
||||||
newLocals.Add(local);
|
newLocals.Add(local);
|
||||||
|
newLocalsDict[local] = true;
|
||||||
foreach (var info in usedLocals[local])
|
foreach (var info in usedLocals[local])
|
||||||
info.block.Instructions[info.index] = new Instr(optimizeLocalInstr(info.block.Instructions[info.index], local, (uint)newIndex));
|
info.block.Instructions[info.index] = new Instr(optimizeLocalInstr(info.block.Instructions[info.index], local, (uint)newIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We can't remove all locals. Locals that reference another assembly will
|
||||||
|
// cause the CLR to load that assembly before the method is executed if it
|
||||||
|
// hasn't been loaded yet. This is a side effect the program may depend on.
|
||||||
|
// At least one program has this dependency and will crash if we remove the
|
||||||
|
// unused local. This took a while to figure out...
|
||||||
|
var keptAssemblies = new Dictionary<string, bool>(StringComparer.Ordinal);
|
||||||
|
foreach (var local in locals) {
|
||||||
|
if (newLocalsDict.ContainsKey(local))
|
||||||
|
continue;
|
||||||
|
var defAsm = local.Type.DefinitionAssembly;
|
||||||
|
if (defAsm == null)
|
||||||
|
continue; // eg. fnptr
|
||||||
|
if (defAsm == method.DeclaringType.OwnerModule.Assembly)
|
||||||
|
continue; // this assembly is always loaded
|
||||||
|
if (defAsm.IsCorLib())
|
||||||
|
continue; // mscorlib is always loaded
|
||||||
|
var asmName = defAsm.FullName;
|
||||||
|
if (keptAssemblies.ContainsKey(asmName))
|
||||||
|
continue;
|
||||||
|
keptAssemblies[asmName] = true;
|
||||||
|
newLocals.Add(local);
|
||||||
|
}
|
||||||
|
|
||||||
int numRemoved = locals.Count - newLocals.Count;
|
int numRemoved = locals.Count - newLocals.Count;
|
||||||
locals.Clear();
|
locals.Clear();
|
||||||
foreach (var local in newLocals)
|
foreach (var local in newLocals)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user