|
// ----------------------------------------------------------------------------------------------
// Copyright (c) Mattias H�gstr�m.
// ----------------------------------------------------------------------------------------------
// This source code is subject to terms and conditions of the Microsoft Public License. A
// copy of the license can be found in the License.html file at the root of this distribution.
// If you cannot locate the Microsoft Public License, please send an email to
// dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
// by the terms of the Microsoft Public License.
// ----------------------------------------------------------------------------------------------
// You must not remove this notice, or any other, from this software.
// ----------------------------------------------------------------------------------------------
#include "stdafx.h"
#include <cor.h>
#include "OpCodeParser.h"
ULONG OpCodeParser::ReplaceFunctionCall(BYTE* opCodeBytes, ULONG length, mdMemberRef fromMemberRef, mdMemberRef toMemberRef)
{
ULONG count = 0;
ULONG index = 0;
while (index < length)
{
BYTE opCode = opCodeBytes[index];
if (IsFunctionCall(opCode))
{
int addressIndex = index + 1;
BYTE* address = opCodeBytes + addressIndex;
mdMemberRef* memberRefAddress = reinterpret_cast<mdMemberRef*>(address);
mdMemberRef memberRef = *memberRefAddress;
if (fromMemberRef == memberRef)
{
*memberRefAddress = toMemberRef;
count++;
}
}
ULONG opCodeSize = InstructionSize(opCodeBytes + index);
index += opCodeSize;
}
return count;
}
ULONG OpCodeParser::CountFunctionCalls(const BYTE* opCodeBytes, ULONG length)
{
ULONG count = 0;
ULONG index = 0;
while (index < length)
{
BYTE opCode = opCodeBytes[index];
if (IsFunctionCall(opCode))
count++;
ULONG opCodeSize = InstructionSize(opCodeBytes + index);
index += opCodeSize;
}
return count;
}
bool OpCodeParser::IsFunctionCall(BYTE opCode)
{
switch (opCode)
{
case 0x28:
return true;
case 0x29:
default:
return false;
}
}
ULONG OpCodeParser::InstructionSize(const BYTE* opCodeBytes)
{
const int tokenSize = sizeof(mdToken);
const int int8Size = 1;
const int int32Size = 4;
const int int64Size = 8;
const int float32Size = 4;
const int float64Size = 8;
BYTE opCode = *opCodeBytes;
//__debugbreak();
if ((0x00 <= opCode) && (opCode <= 0x0d))
return 1;
if ((0x0e <= opCode) && (opCode <= 0x13))
return 1 + int8Size;
if ((0x14 <= opCode) && (opCode <= 0x1e))
return 1;
if ((0x2b <= opCode) && (opCode <= 0x37))
return 1 + int8Size;
if ((0x38 <= opCode) && (opCode <= 0x44))
return 1 + int32Size;
if ((0x46 <= opCode) && (opCode <= 0x6e))
return 1;
if ((0x6f <= opCode) && (opCode <= 0x75))
return 1 + tokenSize;
if ((0x7b <= opCode) && (opCode <= 0x81))
return 1 + tokenSize;
if ((0x82 <= opCode) && (opCode <= 0x8b))
return 1;
if ((0x90 <= opCode) && (opCode <= 0xa2))
return 1;
if ((0xb3 <= opCode) && (opCode <= 0xba))
return 1;
if ((0xd1 <= opCode) && (opCode <= 0xdc))
return 1;
switch (opCode)
{
case 0x1f:
return 1 + int8Size;
case 0x20:
return 1 + int32Size;
case 0x21:
return 1 + int64Size;
case 0x22:
return 1 + float32Size;
case 0x23:
return 1 + float64Size;
case 0x25:
case 0x26:
return 1;
case 0x27:
case 0x28:
case 0x29:
return 1 + tokenSize;
case 0x2a:
return 1;
case 0x45:
{
BYTE length = opCodeBytes[1];
return 1 + 1+ length;
}
case 0x76:
case 0x7a:
return 1;
case 0x79:
case 0x8c:
case 0x8d:
return 1 + tokenSize;
case 0x8e:
return 1;
case 0x8f:
return 1 + tokenSize;
case 0xa3:
case 0xa4:
case 0xa5:
return 1 + tokenSize;
case 0xc2:
case 0xc6:
case 0xd0:
return 1+ tokenSize;
case 0xc3:
return 1;
case 0xdd:
return 1 + int32Size;
case 0xde:
return 1 + int8Size;
case 0xdf:
case 0xe0:
return 1;
}
if (opCode == 0xfe)
{
BYTE extOpCode = opCodeBytes[1];
if ((0x00 <= extOpCode) && (extOpCode <= 0x05))
return 1;
if ((0x09 <= extOpCode) && (extOpCode <= 0x0e))
return 1 + int32Size;
switch (extOpCode)
{
case 0x06:
case 0x07:
return 1 + tokenSize;
case 0x0f:
case 0x11:
return 1;
case 0x12:
return 1 + int8Size;
case 0x13:
case 0x14:
return 1;
case 0x15:
case 0x16:
return 1 + tokenSize;
case 0x17:
case 0x18:
case 0x1a:
return 1;
case 0x1c:
return 1 + tokenSize;
case 0x1d:
case 0x1e:
return 1;
}
}
__debugbreak();
throw "Unrecognized opcode";
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Mattias works at Visma, a leading Nordic ERP solution provider. He has good knowledge in C++/.Net development, test tool development, and debugging. His great passion is memory dump analysis. He likes giving talks and courses.