Dnspy/Extensions/dnSpy.AsmEditor/Hex/InstructionUtils.cs

93 lines
2.4 KiB
C#
Raw Normal View History

2021-09-20 18:20:01 +02:00
/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using dnlib.DotNet;
using dnlib.IO;
namespace dnSpy.AsmEditor.Hex {
static class InstructionUtils {
public static ulong GetTotalMethodBodyLength(MethodDef md) {
if (md is null || md.RVA == 0)
return 0;
var mod = md.Module as ModuleDefMD;//TODO: Support CorModuleDef
if (mod is null)
return 0;
try {
var reader = mod.Metadata.PEImage.CreateReader();
reader.Position = (uint)mod.Metadata.PEImage.ToFileOffset(md.RVA);
var start = reader.Position;
if (!ReadHeader(ref reader, out ushort flags, out uint codeSize))
return 0;
reader.Position += codeSize;
if ((flags & 8) != 0) {
reader.Position = (reader.Position + 3) & ~3U;
byte b = reader.ReadByte();
if ((b & 0x3F) != 1)
reader.Position--;
else if ((b & 0x40) != 0) {
reader.Position--;
uint num = (ushort)((reader.ReadUInt32() >> 8) / 24);
reader.Position += num * 24;
}
else {
uint num = (ushort)((uint)reader.ReadByte() / 12);
reader.Position += 2 + num * 12;
}
}
return reader.Position - start;
}
catch {
return 0;
}
}
static bool ReadHeader(ref DataReader reader, out ushort flags, out uint codeSize) {
byte b = reader.ReadByte();
switch (b & 7) {
case 2:
case 6:
flags = 2;
codeSize = (uint)(b >> 2);
return true;
case 3:
flags = (ushort)((reader.ReadByte() << 8) | b);
uint headerSize = (byte)(flags >> 12);
ushort maxStack = reader.ReadUInt16();
codeSize = reader.ReadUInt32();
uint localVarSigTok = reader.ReadUInt32();
reader.Position = reader.Position - 12 + headerSize * 4;
if (headerSize < 3)
flags &= 0xFFF7;
return true;
default:
flags = 0;
codeSize = 0;
return false;
}
}
}
}