Update detours library.

This commit is contained in:
Mr_Goldberg 2020-05-20 18:40:59 -04:00
parent 3b3dc98b3a
commit 7039d10159
No known key found for this signature in database
GPG key ID: 8597D87419DEF278
7 changed files with 308 additions and 176 deletions

View file

@ -7,28 +7,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
//
#if _MSC_VER >= 1900
#pragma warning(push)
#pragma warning(disable:4091) // empty typedef
#endif
#define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
#include <windows.h>
#include <limits.h>
// #define DETOUR_DEBUG 1
#define DETOURS_INTERNAL
#include "detours.h"
#include <limits.h>
#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
#error detours.h version mismatch
#endif
#if _MSC_VER >= 1900
#pragma warning(pop)
#endif
#undef ASSERT
#define ASSERT(x)
@ -260,6 +247,11 @@ class CDetourDis
#define ENTRY_CopyFF ENTRY_DataIgnored &CDetourDis::CopyFF
#define ENTRY_CopyVex2 ENTRY_DataIgnored &CDetourDis::CopyVex2
#define ENTRY_CopyVex3 ENTRY_DataIgnored &CDetourDis::CopyVex3
#define ENTRY_CopyEvex ENTRY_DataIgnored &CDetourDis::CopyEvex // 62, 3 byte payload, then normal with implied prefixes like vex
#define ENTRY_CopyXop ENTRY_DataIgnored &CDetourDis::CopyXop // 0x8F ... POP /0 or AMD XOP
#define ENTRY_CopyBytesXop 5, 5, 4, 0, 0, &CDetourDis::CopyBytes // 0x8F xop1 xop2 opcode modrm
#define ENTRY_CopyBytesXop1 6, 6, 4, 0, 0, &CDetourDis::CopyBytes // 0x8F xop1 xop2 opcode modrm ... imm8
#define ENTRY_CopyBytesXop4 9, 9, 4, 0, 0, &CDetourDis::CopyBytes // 0x8F xop1 xop2 opcode modrm ... imm32
#define ENTRY_Invalid ENTRY_DataIgnored &CDetourDis::Invalid
#define ENTRY_End ENTRY_DataIgnored NULL
@ -289,6 +281,9 @@ class CDetourDis
PBYTE CopyVex2(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
PBYTE CopyVex3(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
PBYTE CopyVexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc);
PBYTE CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p);
PBYTE CopyEvex(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
PBYTE CopyXop(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
protected:
static const COPYENTRY s_rceCopyTable[257];
@ -303,6 +298,7 @@ class CDetourDis
BOOL m_bAddressOverride;
BOOL m_bRaxOverride; // AMD64 only
BOOL m_bVex;
BOOL m_bEvex;
BOOL m_bF2;
BOOL m_bF3; // x86 only
BYTE m_nSegmentOverride;
@ -337,6 +333,7 @@ CDetourDis::CDetourDis(_Out_opt_ PBYTE *ppbTarget, _Out_opt_ LONG *plExtra)
m_bF2 = FALSE;
m_bF3 = FALSE;
m_bVex = FALSE;
m_bEvex = FALSE;
m_ppbTarget = ppbTarget ? ppbTarget : &m_pbScratchTarget;
m_plExtra = plExtra ? plExtra : &m_lScratchExtra;
@ -368,8 +365,11 @@ PBYTE CDetourDis::CopyBytes(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
{
UINT nBytesFixed;
ASSERT(!m_bVex || pEntry->nFlagBits == 0);
ASSERT(!m_bVex || pEntry->nFixedSize == pEntry->nFixedSize16);
if (m_bVex || m_bEvex)
{
ASSERT(pEntry->nFlagBits == 0);
ASSERT(pEntry->nFixedSize == pEntry->nFixedSize16);
}
UINT const nModOffset = pEntry->nModOffset;
UINT const nFlagBits = pEntry->nFlagBits;
@ -748,33 +748,42 @@ PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
return pbOut;
}
PBYTE CDetourDis::CopyVexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc)
PBYTE CDetourDis::CopyVexEvexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc, BYTE p)
// m is first instead of last in the hopes of pbDst/pbSrc being
// passed along efficiently in the registers they were already in.
{
static const COPYENTRY ceF38 = { 0x38, ENTRY_CopyBytes2Mod };
static const COPYENTRY ceF3A = { 0x3A, ENTRY_CopyBytes2Mod1 };
static const COPYENTRY Invalid = { 0xC4, ENTRY_Invalid };
static const COPYENTRY ceInvalid = { 0xC4, ENTRY_Invalid };
m_bVex = TRUE;
REFCOPYENTRY pEntry;
switch (m) {
default: pEntry = &Invalid; break;
case 1: pEntry = &s_rceCopyTable0F[pbSrc[0]]; break;
case 2: pEntry = &ceF38; break;
case 3: pEntry = &ceF3A; break;
}
switch (pbSrc[-1] & 3) { // p in last byte
switch (p & 3) {
case 0: break;
case 1: m_bOperandOverride = TRUE; break;
case 2: m_bF3 = TRUE; break;
case 3: m_bF2 = TRUE; break;
}
return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
REFCOPYENTRY pEntry;
switch (m) {
default: return Invalid(&ceInvalid, pbDst, pbSrc);
case 1: pEntry = &s_rceCopyTable0F[pbSrc[0]];
return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
case 2: return CopyBytes(&ceF38, pbDst, pbSrc);
case 3: return CopyBytes(&ceF3A, pbDst, pbSrc);
}
}
PBYTE CDetourDis::CopyVexCommon(BYTE m, PBYTE pbDst, PBYTE pbSrc)
// m is first instead of last in the hopes of pbDst/pbSrc being
// passed along efficiently in the registers they were already in.
{
m_bVex = TRUE;
BYTE const p = (BYTE)(pbSrc[-1] & 3); // p in last byte
return CopyVexEvexCommon(m, pbDst, pbSrc, p);
}
PBYTE CDetourDis::CopyVex3(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
// 3 byte VEX prefix 0xC4
{
@ -835,6 +844,78 @@ PBYTE CDetourDis::CopyVex2(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
return CopyVexCommon(1, pbDst + 2, pbSrc + 2);
}
PBYTE CDetourDis::CopyEvex(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
// 62, 3 byte payload, x86 with implied prefixes like Vex
// for 32bit, mode 0xC0 else fallback to bound /r
{
// NOTE: Intel and Wikipedia number these differently.
// Intel says 0-2, Wikipedia says 1-3.
BYTE const p0 = pbSrc[1];
#ifdef DETOURS_X86
const static COPYENTRY ceBound = { 0x62, ENTRY_CopyBytes2Mod };
if ((p0 & 0xC0) != 0xC0) {
return CopyBytes(&ceBound, pbDst, pbSrc);
}
#endif
static const COPYENTRY ceInvalid = { 0x62, ENTRY_Invalid };
if ((p0 & 0x0C) != 0)
return Invalid(&ceInvalid, pbDst, pbSrc);
BYTE const p1 = pbSrc[2];
if ((p1 & 0x04) != 0x04)
return Invalid(&ceInvalid, pbDst, pbSrc);
// Copy 4 byte prefix.
*(UNALIGNED ULONG *)pbDst = *(UNALIGNED ULONG*)pbSrc;
m_bEvex = TRUE;
#ifdef DETOURS_X64
m_bRaxOverride |= !!(p1 & 0x80); // w
#endif
return CopyVexEvexCommon(p0 & 3u, pbDst + 4, pbSrc + 4, p1 & 3u);
}
PBYTE CDetourDis::CopyXop(REFCOPYENTRY, PBYTE pbDst, PBYTE pbSrc)
/* 3 byte AMD XOP prefix 0x8F
byte0: 0x8F
byte1: RXBmmmmm
byte2: WvvvvLpp
byte3: opcode
mmmmm >= 8, else pop
mmmmm only otherwise defined for 8, 9, A.
pp is like VEX but only instructions with 0 are defined
*/
{
const static COPYENTRY cePop = { 0x8F, ENTRY_CopyBytes2Mod };
const static COPYENTRY ceXop = { 0x8F, ENTRY_CopyBytesXop };
const static COPYENTRY ceXop1 = { 0x8F, ENTRY_CopyBytesXop1 };
const static COPYENTRY ceXop4 = { 0x8F, ENTRY_CopyBytesXop4 };
BYTE const m = (BYTE)(pbSrc[1] & 0x1F);
ASSERT(m <= 10);
switch (m)
{
default:
return CopyBytes(&cePop, pbDst, pbSrc);
case 8: // modrm with 8bit immediate
return CopyBytes(&ceXop1, pbDst, pbSrc);
case 9: // modrm with no immediate
return CopyBytes(&ceXop, pbDst, pbSrc);
case 10: // modrm with 32bit immediate
return CopyBytes(&ceXop4, pbDst, pbSrc);
}
}
//////////////////////////////////////////////////////////////////////////////
//
PBYTE CDetourDis::s_pbModuleBeg = NULL;
@ -1030,11 +1111,11 @@ const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable[257] =
#ifdef DETOURS_X64
{ 0x60, ENTRY_Invalid }, // Invalid
{ 0x61, ENTRY_Invalid }, // Invalid
{ 0x62, ENTRY_Invalid }, // Invalid (not yet implemented Intel EVEX support)
{ 0x62, ENTRY_CopyEvex }, // EVEX / AVX512
#else
{ 0x60, ENTRY_CopyBytes1 }, // PUSHAD
{ 0x61, ENTRY_CopyBytes1 }, // POPAD
{ 0x62, ENTRY_CopyBytes2Mod }, // BOUND /r
{ 0x62, ENTRY_CopyEvex }, // BOUND /r and EVEX / AVX512
#endif
{ 0x63, ENTRY_CopyBytes2Mod }, // 32bit ARPL /r, 64bit MOVSXD
{ 0x64, ENTRY_CopyBytesSegment }, // FS prefix
@ -1084,7 +1165,7 @@ const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable[257] =
{ 0x8C, ENTRY_CopyBytes2Mod }, // MOV /r
{ 0x8D, ENTRY_CopyBytes2Mod }, // LEA /r
{ 0x8E, ENTRY_CopyBytes2Mod }, // MOV /r
{ 0x8F, ENTRY_CopyBytes2Mod }, // POP /0
{ 0x8F, ENTRY_CopyXop }, // POP /0 or AMD XOP
{ 0x90, ENTRY_CopyBytes1 }, // NOP
{ 0x91, ENTRY_CopyBytes1 }, // XCHG
{ 0x92, ENTRY_CopyBytes1 }, // XCHG