|
|
@ -426,13 +426,12 @@ namespace ICSharpCode.Decompiler.ILAst |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Occasionally the compiler generates unreachable code - it can be usually just ignored
|
|
|
|
// Occasionally the compilers or obfuscators generate unreachable code (which migt be intentonally invalid)
|
|
|
|
var reachableBody = body.Where(b => b.StackBefore != null); |
|
|
|
// I belive it is safe to just remove it
|
|
|
|
var unreachableBody = body.Where(b => b.StackBefore == null); |
|
|
|
body.RemoveAll(b => b.StackBefore == null); |
|
|
|
|
|
|
|
|
|
|
|
// Genertate temporary variables to replace stack
|
|
|
|
// Genertate temporary variables to replace stack
|
|
|
|
// Unrachable code does not need temporary variables - the values are never pushed on the stack for consuption
|
|
|
|
foreach(ByteCode byteCode in body) { |
|
|
|
foreach(ByteCode byteCode in reachableBody) { |
|
|
|
|
|
|
|
int argIdx = 0; |
|
|
|
int argIdx = 0; |
|
|
|
int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count; |
|
|
|
int popCount = byteCode.PopCount ?? byteCode.StackBefore.Count; |
|
|
|
for (int i = byteCode.StackBefore.Count - popCount; i < byteCode.StackBefore.Count; i++) { |
|
|
|
for (int i = byteCode.StackBefore.Count - popCount; i < byteCode.StackBefore.Count; i++) { |
|
|
@ -450,19 +449,18 @@ namespace ICSharpCode.Decompiler.ILAst |
|
|
|
|
|
|
|
|
|
|
|
// Try to use single temporary variable insted of several if possilbe (especially useful for dup)
|
|
|
|
// Try to use single temporary variable insted of several if possilbe (especially useful for dup)
|
|
|
|
// This has to be done after all temporary variables are assigned so we know about all loads
|
|
|
|
// This has to be done after all temporary variables are assigned so we know about all loads
|
|
|
|
// Unrachable code will not have any StoreTo
|
|
|
|
foreach(ByteCode byteCode in body) { |
|
|
|
foreach(ByteCode byteCode in reachableBody) { |
|
|
|
|
|
|
|
if (byteCode.StoreTo != null && byteCode.StoreTo.Count > 1) { |
|
|
|
if (byteCode.StoreTo != null && byteCode.StoreTo.Count > 1) { |
|
|
|
var locVars = byteCode.StoreTo; |
|
|
|
var locVars = byteCode.StoreTo; |
|
|
|
// For each of the variables, find the location where it is loaded - there should be preciesly one
|
|
|
|
// For each of the variables, find the location where it is loaded - there should be preciesly one
|
|
|
|
var loadedBy = locVars.Select(locVar => reachableBody.SelectMany(bc => bc.StackBefore).Single(s => s.LoadFrom == locVar)).ToList(); |
|
|
|
var loadedBy = locVars.Select(locVar => body.SelectMany(bc => bc.StackBefore).Single(s => s.LoadFrom == locVar)).ToList(); |
|
|
|
// We now know that all the variables have a single load,
|
|
|
|
// We now know that all the variables have a single load,
|
|
|
|
// Let's make sure that they have also a single store - us
|
|
|
|
// Let's make sure that they have also a single store - us
|
|
|
|
if (loadedBy.All(slot => slot.PushedBy.Length == 1 && slot.PushedBy[0] == byteCode)) { |
|
|
|
if (loadedBy.All(slot => slot.PushedBy.Length == 1 && slot.PushedBy[0] == byteCode)) { |
|
|
|
// Great - we can reduce everything into single variable
|
|
|
|
// Great - we can reduce everything into single variable
|
|
|
|
ILVariable tmpVar = new ILVariable() { Name = string.Format("expr_{0:X2}", byteCode.Offset), IsGenerated = true }; |
|
|
|
ILVariable tmpVar = new ILVariable() { Name = string.Format("expr_{0:X2}", byteCode.Offset), IsGenerated = true }; |
|
|
|
byteCode.StoreTo = new List<ILVariable>() { tmpVar }; |
|
|
|
byteCode.StoreTo = new List<ILVariable>() { tmpVar }; |
|
|
|
foreach(ByteCode bc in reachableBody) { |
|
|
|
foreach(ByteCode bc in body) { |
|
|
|
for (int i = 0; i < bc.StackBefore.Count; i++) { |
|
|
|
for (int i = 0; i < bc.StackBefore.Count; i++) { |
|
|
|
// Is it one of the variable to be merged?
|
|
|
|
// Is it one of the variable to be merged?
|
|
|
|
if (locVars.Contains(bc.StackBefore[i].LoadFrom)) { |
|
|
|
if (locVars.Contains(bc.StackBefore[i].LoadFrom)) { |
|
|
@ -658,12 +656,14 @@ namespace ICSharpCode.Decompiler.ILAst |
|
|
|
// Find the first and widest scope
|
|
|
|
// Find the first and widest scope
|
|
|
|
int tryStart = ehs.Min(eh => eh.TryStart.Offset); |
|
|
|
int tryStart = ehs.Min(eh => eh.TryStart.Offset); |
|
|
|
int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset); |
|
|
|
int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset); |
|
|
|
var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList(); |
|
|
|
var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).OrderBy(eh => eh.TryStart.Offset).ToList(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Remember that any part of the body migt have been removed due to unreachability
|
|
|
|
|
|
|
|
|
|
|
|
// Cut all instructions up to the try block
|
|
|
|
// Cut all instructions up to the try block
|
|
|
|
{ |
|
|
|
{ |
|
|
|
int tryStartIdx; |
|
|
|
int tryStartIdx = 0; |
|
|
|
for (tryStartIdx = 0; body[tryStartIdx].Offset != tryStart; tryStartIdx++); |
|
|
|
while (tryStartIdx < body.Count && body[tryStartIdx].Offset < tryStart) tryStartIdx++; |
|
|
|
ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx))); |
|
|
|
ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx))); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -671,24 +671,22 @@ namespace ICSharpCode.Decompiler.ILAst |
|
|
|
{ |
|
|
|
{ |
|
|
|
HashSet<ExceptionHandler> nestedEHs = new HashSet<ExceptionHandler>(ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd))); |
|
|
|
HashSet<ExceptionHandler> nestedEHs = new HashSet<ExceptionHandler>(ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd))); |
|
|
|
ehs.ExceptWith(nestedEHs); |
|
|
|
ehs.ExceptWith(nestedEHs); |
|
|
|
int tryEndIdx; |
|
|
|
int tryEndIdx = 0; |
|
|
|
for (tryEndIdx = 0; tryEndIdx < body.Count && body[tryEndIdx].Offset != tryEnd; tryEndIdx++); |
|
|
|
while (tryEndIdx < body.Count && body[tryEndIdx].Offset < tryEnd) tryEndIdx++; |
|
|
|
tryCatchBlock.TryBlock = new ILBlock(ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs)); |
|
|
|
tryCatchBlock.TryBlock = new ILBlock(ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Cut all handlers
|
|
|
|
// Cut all handlers
|
|
|
|
tryCatchBlock.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>(); |
|
|
|
tryCatchBlock.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>(); |
|
|
|
foreach(ExceptionHandler eh in handlers) { |
|
|
|
foreach(ExceptionHandler eh in handlers) { |
|
|
|
int startIndex; |
|
|
|
int handlerEndOffset = eh.HandlerEnd == null ? methodDef.Body.CodeSize : eh.HandlerEnd.Offset; |
|
|
|
for (startIndex = 0; body[startIndex].Offset != eh.HandlerStart.Offset; startIndex++); |
|
|
|
int startIdx = 0; |
|
|
|
int endInclusiveIndex; |
|
|
|
while (startIdx < body.Count && body[startIdx].Offset < eh.HandlerStart.Offset) startIdx++; |
|
|
|
if (eh.HandlerEnd == null) endInclusiveIndex = body.Count - 1; |
|
|
|
int endIdx = 0; |
|
|
|
// Note that the end(exclusive) instruction may not necessarly be in our body
|
|
|
|
while (endIdx < body.Count && body[endIdx].Offset < handlerEndOffset) endIdx++; |
|
|
|
else for (endInclusiveIndex = 0; body[endInclusiveIndex].Next.Offset != eh.HandlerEnd.Offset; endInclusiveIndex++); |
|
|
|
HashSet<ExceptionHandler> nestedEHs = new HashSet<ExceptionHandler>(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < handlerEndOffset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= handlerEndOffset))); |
|
|
|
int count = 1 + endInclusiveIndex - startIndex; |
|
|
|
|
|
|
|
HashSet<ExceptionHandler> nestedEHs = new HashSet<ExceptionHandler>(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < eh.HandlerEnd.Offset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= eh.HandlerEnd.Offset))); |
|
|
|
|
|
|
|
ehs.ExceptWith(nestedEHs); |
|
|
|
ehs.ExceptWith(nestedEHs); |
|
|
|
List<ILNode> handlerAst = ConvertToAst(body.CutRange(startIndex, count), nestedEHs); |
|
|
|
List<ILNode> handlerAst = ConvertToAst(body.CutRange(startIdx, endIdx - startIdx), nestedEHs); |
|
|
|
if (eh.HandlerType == ExceptionHandlerType.Catch) { |
|
|
|
if (eh.HandlerType == ExceptionHandlerType.Catch) { |
|
|
|
ILTryCatchBlock.CatchBlock catchBlock = new ILTryCatchBlock.CatchBlock() { |
|
|
|
ILTryCatchBlock.CatchBlock catchBlock = new ILTryCatchBlock.CatchBlock() { |
|
|
|
ExceptionType = eh.CatchType, |
|
|
|
ExceptionType = eh.CatchType, |
|
|
|