Browse Source

Merge branch 'master' into feature/ReferenceAssemblyOverly

pull/3013/head
workgroupengineering 1 year ago committed by GitHub
parent
commit
757b5d556d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 98
      ICSharpCode.Decompiler/Disassembler/ILParser.cs
  2. 2
      ICSharpCode.Decompiler/Disassembler/ILStructure.cs
  3. 3
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  4. 10
      ICSharpCode.Decompiler/IL/ILReader.cs
  5. 2
      ICSharpCode.ILSpyX/FileLoaders/XamarinCompressedFileLoader.cs

98
ICSharpCode.Decompiler/Disassembler/ILParser.cs

@ -30,18 +30,24 @@ namespace ICSharpCode.Decompiler.Disassembler
public static ILOpCode DecodeOpCode(this ref BlobReader blob) public static ILOpCode DecodeOpCode(this ref BlobReader blob)
{ {
byte opCodeByte = blob.ReadByte(); byte opCodeByte = blob.ReadByte();
return (ILOpCode)(opCodeByte == 0xFE ? 0xFE00 + blob.ReadByte() : opCodeByte); if (opCodeByte == 0xFE && blob.RemainingBytes >= 1)
{
return (ILOpCode)(0xFE00 + blob.ReadByte());
}
else
{
return (ILOpCode)opCodeByte;
}
} }
public static void SkipOperand(this ref BlobReader blob, ILOpCode opCode) internal static int OperandSize(this OperandType opType)
{ {
switch (opCode.GetOperandType()) switch (opType)
{ {
// 64-bit // 64-bit
case OperandType.I8: case OperandType.I8:
case OperandType.R: case OperandType.R:
blob.Offset += 8; return 8;
break;
// 32-bit // 32-bit
case OperandType.BrTarget: case OperandType.BrTarget:
case OperandType.Field: case OperandType.Field:
@ -52,37 +58,91 @@ namespace ICSharpCode.Decompiler.Disassembler
case OperandType.Tok: case OperandType.Tok:
case OperandType.Type: case OperandType.Type:
case OperandType.ShortR: case OperandType.ShortR:
blob.Offset += 4; return 4;
break;
// (n + 1) * 32-bit // (n + 1) * 32-bit
case OperandType.Switch: case OperandType.Switch:
uint n = blob.ReadUInt32(); return 4; // minimum 4, usually more
blob.Offset += (int)(n * 4); case OperandType.Variable: // 16-bit
break; return 2;
// 16-bit
case OperandType.Variable:
blob.Offset += 2;
break;
// 8-bit // 8-bit
case OperandType.ShortVariable: case OperandType.ShortVariable:
case OperandType.ShortBrTarget: case OperandType.ShortBrTarget:
case OperandType.ShortI: case OperandType.ShortI:
blob.Offset++; return 1;
break; default:
return 0;
}
}
public static void SkipOperand(this ref BlobReader blob, ILOpCode opCode)
{
var opType = opCode.GetOperandType();
int operandSize;
if (opType == OperandType.Switch)
{
uint n = blob.RemainingBytes >= 4 ? blob.ReadUInt32() : uint.MaxValue;
if (n < int.MaxValue / 4)
{
operandSize = (int)(n * 4);
}
else
{
operandSize = int.MaxValue;
}
}
else
{
operandSize = opType.OperandSize();
}
if (operandSize <= blob.RemainingBytes)
{
blob.Offset += operandSize;
}
else
{
// ignore missing/partial operand at end of body
blob.Offset = blob.Length;
} }
} }
public static int DecodeBranchTarget(this ref BlobReader blob, ILOpCode opCode) public static int DecodeBranchTarget(this ref BlobReader blob, ILOpCode opCode)
{ {
return (opCode.GetBranchOperandSize() == 4 ? blob.ReadInt32() : blob.ReadSByte()) + blob.Offset; int opSize = opCode.GetBranchOperandSize();
if (opSize <= blob.RemainingBytes)
{
int relOffset = opSize == 4 ? blob.ReadInt32() : blob.ReadSByte();
return unchecked(relOffset + blob.Offset);
}
else
{
return int.MinValue;
}
} }
public static int[] DecodeSwitchTargets(this ref BlobReader blob) public static int[] DecodeSwitchTargets(this ref BlobReader blob)
{ {
int[] targets = new int[blob.ReadUInt32()]; if (blob.RemainingBytes < 4)
{
blob.Offset += blob.RemainingBytes;
return new int[0];
}
uint numTargets = blob.ReadUInt32();
bool numTargetOverflow = false;
if (numTargets > blob.RemainingBytes / 4)
{
numTargets = (uint)(blob.RemainingBytes / 4);
numTargetOverflow = true;
}
int[] targets = new int[numTargets];
int offset = blob.Offset + 4 * targets.Length; int offset = blob.Offset + 4 * targets.Length;
for (int i = 0; i < targets.Length; i++) for (int i = 0; i < targets.Length; i++)
targets[i] = blob.ReadInt32() + offset; {
targets[i] = unchecked(blob.ReadInt32() + offset);
}
if (numTargetOverflow)
{
blob.Offset += blob.RemainingBytes;
}
return targets; return targets;
} }

2
ICSharpCode.Decompiler/Disassembler/ILStructure.cs

@ -171,6 +171,8 @@ namespace ICSharpCode.Decompiler.Disassembler
// special case: don't consider the loop-like structure of "continue;" statements to be nested loops // special case: don't consider the loop-like structure of "continue;" statements to be nested loops
if (this.Type == ILStructureType.Loop && newStructure.Type == ILStructureType.Loop && newStructure.StartOffset == this.StartOffset) if (this.Type == ILStructureType.Loop && newStructure.Type == ILStructureType.Loop && newStructure.StartOffset == this.StartOffset)
return false; return false;
if (newStructure.StartOffset < 0)
return false;
// use <= for end-offset comparisons because both end and EndOffset are exclusive // use <= for end-offset comparisons because both end and EndOffset are exclusive
Debug.Assert(StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= EndOffset); Debug.Assert(StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= EndOffset);

3
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -350,7 +350,8 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
} }
ILOpCode opCode = ILParser.DecodeOpCode(ref blob); ILOpCode opCode = ILParser.DecodeOpCode(ref blob);
if (opCode.IsDefined()) OperandType opType = opCode.GetOperandType();
if (opCode.IsDefined() && opType.OperandSize() <= blob.RemainingBytes)
{ {
WriteRVA(blob, offset + methodRva, opCode); WriteRVA(blob, offset + methodRva, opCode);
output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true); output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true);

10
ICSharpCode.Decompiler/IL/ILReader.cs

@ -1780,7 +1780,15 @@ namespace ICSharpCode.Decompiler.IL
DecodedInstruction DecodeCallIndirect() DecodedInstruction DecodeCallIndirect()
{ {
var signatureHandle = (StandaloneSignatureHandle)ReadAndDecodeMetadataToken(); StandaloneSignatureHandle signatureHandle;
try
{
signatureHandle = (StandaloneSignatureHandle)ReadAndDecodeMetadataToken();
}
catch (InvalidCastException ex)
{
throw new BadImageFormatException("Invalid calli metadata token", ex);
}
var (header, fpt) = module.DecodeMethodSignature(signatureHandle, genericContext); var (header, fpt) = module.DecodeMethodSignature(signatureHandle, genericContext);
var functionPointer = Pop(StackType.I); var functionPointer = Pop(StackType.I);
int firstArgument = header.IsInstance ? 1 : 0; int firstArgument = header.IsInstance ? 1 : 0;

2
ICSharpCode.ILSpyX/FileLoaders/XamarinCompressedFileLoader.cs

@ -59,7 +59,7 @@ namespace ICSharpCode.ILSpyX.FileLoaders
: MetadataReaderOptions.None; : MetadataReaderOptions.None;
return new LoadResult { return new LoadResult {
MetadataFile = new PEFile(fileName, stream, PEStreamOptions.PrefetchEntireImage, metadataOptions: options) MetadataFile = new PEFile(fileName, uncompressedStream, PEStreamOptions.PrefetchEntireImage, metadataOptions: options)
}; };
} }
} }

Loading…
Cancel
Save