This commit is contained in:
2022-09-06 00:08:26 +08:00
parent e17ffc3965
commit 91d57c13f0
232 changed files with 191628 additions and 250 deletions

View File

@@ -0,0 +1,76 @@
##############################################################################
##
## Makefile for Detours Test Programs.
##
## Microsoft Research Detours Package
##
## Copyright (c) Microsoft Corporation. All rights reserved.
##
!include ..\common.mak
# temporarily disable this test for ARM64
!if "$(DETOURS_TARGET_PROCESSOR)" != "ARM64"
LIBS=$(LIBS) kernel32.lib
all: dirs \
$(BIND)\disas.exe \
!IF $(DETOURS_SOURCE_BROWSING)==1
$(OBJD)\disas.bsc
!ENDIF
clean:
-del *~ *.obj *.sbr *.lst 2>nul
-del $(BIND)\disas.* 2> nul
-rmdir /q /s $(OBJD) 2>nul
realclean: clean
-rmdir /q /s $(OBJDS) 2>nul
dirs:
@if not exist $(BIND) mkdir $(BIND) && echo. Created $(BIND)
@if not exist $(OBJD) mkdir $(OBJD) && echo. Created $(OBJD)
!IF "$(DETOURS_TARGET_PROCESSOR)" == "X86"
$(OBJD)\disasm.obj : x86.cpp
cl $(CFLAGS) /Fe$@ /FAcs /Fa$(OBJD)\x86.lst \
/Fd$(@R).pdb /Fo$(OBJD)\disasm.obj /c x86.cpp
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "X64"
$(OBJD)\disasm.obj : x64.asm
$(ASM) $(AFLAGS) /Fo$(OBJD)\disasm.obj /Fl$(OBJD)\x64.lst x64.asm
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "IA64"
$(OBJD)\disasm.obj : ia64.asm
$(ASM) $(AFLAGS) -o $(OBJD)\disasm.obj ia64.asm
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM"
$(OBJD)\disasm.obj : arm.asm
$(ASM) $(AFLAGS) -list $(OBJD)\arm.lst -o $(OBJD)\disasm.obj arm.asm
!ENDIF
$(BIND)\disas.obj : disas.cpp
$(BIND)\disas.exe : $(OBJD)\disas.obj $(OBJD)\disasm.obj $(DEPS)
cl $(CFLAGS) /Fe$@ /FAcs /Fa$(OBJD)\disas.lst /Fd$(@R).pdb \
$(OBJD)\disas.obj $(OBJD)\disasm.obj \
/link $(LINKFLAGS) $(LIBS) /subsystem:console /entry:WinMainCRTStartup
$(OBJD)\disas.bsc : $(OBJD)\disas.obj
bscmake /v /n /o $@ $(OBJD)\disas.sbr
##############################################################################
test: $(BIND)\disas.exe
$(BIND)\disas.exe
##############################################################################
!else
all:
test:
clean:
realclean:
!endif
################################################################# End of File.

View File

@@ -0,0 +1,232 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Detours Test Program (rlo.asm/disas.exe)
;;
;; Microsoft Research Detours Package
;;
;; Copyright (c) Microsoft Corporation. All rights reserved.
;;
MACRO
BREAK
DCW 0xdefe
MEND
AREA |.text|,ALIGN=2,CODE,READONLY
AREA |.text|,CODE,READONLY
ALIGN 0x1000
EXPORT |TestCodes|
|TestCodes|
; dcw 0xf8df,0xe00e ; 94 = -16 = -12 ; 94 ; 98 + e = a6
; BREAK ; 98 = -14 = -10 ; 98 ; 9c
; dcw 0xf8df,0xe00a ; 9a = -12 = -8 ; 98 ; 9c + a = a6
; BREAK ; 9e = -8 = -4 ; 9c ; a0
; dcw 0xf8df,0xe002 ; a0 = -6 = -2 ; a0 ; a4 + 2 = a6
; BREAK ; a4 = -2 ; a4 ; a8
; movs r2, r0 ; a6 <===
; movs r3, r0 ;
; BREAK
; BREAK
;
; ldr lr,=0xa98765
; ldr pc,=0xa98765
; ldr pc,=0xa98765
; ldr pc,=0xa98765
; BREAK
; BREAK
BREAK
ldr lr, =0xa98765
BREAK
blx lr
BREAK
pop pc
BREAK
pop {r11,pc}
BREAK
pop {r10,r11,pc}
BREAK
pop {r9,r10,r11,pc}
BREAK
pop {r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,pc}
BREAK
ldr.w r0,=0xa98765
BREAK
nop
ldr.w r0,=0xa98765
BREAK
nop
nop
ldr.w r0,=0xa98765
BREAK
ldr r0,=0xa98765
BREAK
ldr.w r0,=0xa98765
BREAK
ldr.w r0,=0xa98765
BREAK
ldr r0,=0xa98765
BREAK
ldr.w r0,=0xa98765
BREAK
ldr.w r0,=0xa98765
BREAK
ldr r0,=0xa98765
BREAK
ldr.w r0,=0xa98765
BREAK
ldr.w r0,=0xa98765
BREAK
ldr r0,=0xa98765
BREAK
nop
ldr r0,=0xa98765
BREAK
nop
nop
ldr r0,=0xa98765
BREAK
nop
ldr r0,=0xa
BREAK
ldr r0,=0xa9
BREAK
ldr r0,=0xa98
BREAK
ldr r0,=0xa987
BREAK
ldr r0,=0xa9876
BREAK
ldr r0,=0xa98765
BREAK
ldr r0,=0xa987654
BREAK
ldr r0,=0xa9876543
;; Simple instructions.
BREAK
adds r0,r0, #5 ; 1d40
BREAK
movs r2, #0 ; 2200
BREAK
movs r3, #0 ; 2300
BREAK
bx lr ; 4770 [FFFFFFFF]
;; Known 16-bit instructions
BREAK
mov r11, sp ; 46eb
BREAK
movs r2, r0 ; 0002
BREAK
push r0, r1 ; b403
BREAK
str r3,[r7,#0x28] ; 62bb
BREAK
bx r5 ; 4728 [FFFFFFFF]
BREAK
blx r5 ; 47a8
BREAK
DCW 0x4878 ; ldr r0, [PC + 0x1E0] ; 4878
BREAK
str r3,[r7,#0x1C] ; 61fb
BREAK
ldr r3,[r7,#0x38] ; 6bbb
BREAK
add r3,sp,#0xCC ; ab33
BREAK
cbz r2,+0x56 ; b34a [00xx1510]
BREAK
cbnz r2,+0x56 ; bb4a [00xx1514]
BREAK
push {r0,r2,r4,r6,lr} ; b555
BREAK
nop ; bf00
;; Placeholder for IT instruction
BREAK
bne +0x6E ; d135 [00xx1538] -??? d137
BREAK
svc #0x24 ; df24
BREAK
b +0x7FE ; e3fd [00xx1cd0] -??? e3ff
;; 32 bit test codes
BREAK
adds r0,r7,#8 ; f1170008
BREAK
str r3,[r5,#0x677] ; f8c53677
BREAK
ldrsh r10,[r5,#0x5A5] ; f9b5a5a5
BREAK
DCW 0xf89f,0x55a5 ;ldrb r5, [+0x5A5] ; f89f55a5
BREAK
bls.w +0x86; 0xf240; 0x8043; // ; f2408041 [00xx157A]
BREAK
bl +0xFE; 0xf7ff; 0xff80; //
BREAK
bl +0xFFE; 0xf7ff; 0xff80; //
BREAK
bl +0xFFFE; 0xf7ff; 0xff80; //
BREAK
bl +0xFFFFE; 0xf7ff; 0xff80; //
BREAK
bl +0xFFFFFE; 0xf7ff; 0xff80; //
BREAK
bl +0xF0; 0xf7ff; 0xff80; //
BREAK
bl +0xFF0; 0xf7ff; 0xff80; //
BREAK
bl +0xFFF0; 0xf7ff; 0xff80; //
BREAK
bl +0xFFFF0; 0xf7ff; 0xff80; //
BREAK
bl +0xFFFFF0; 0xf7ff; 0xff80; //
BREAK
bl +0xF00; 0xf7ff; 0xff80; //
BREAK
bl +0xFF00; 0xf7ff; 0xff80; //
BREAK
bl +0xFFF00; 0xf7ff; 0xff80; //
BREAK
bl +0xFFFF00; 0xf7ff; 0xff80; //
BREAK
DCW 0xf7ff,0xff80
;bl +0xFFFFFF00; 0xf7ff; 0xff80; //
BREAK
DCW 0xf7ff,0xbe02
; b.w ; 0xf7ff; 0xbe02; // (10053528)
BREAK
push {r7,r11,lr}; 0xe92d; 0x4880; //
;; 32 bit expected results
BREAK
adds r0,r7,#8 ; 0xf1170008
BREAK
str r3,[r5,#0x677] ; 0xf8c53677
BREAK
ldrsh r10,[r5,#0x5A5] ; 0xf9b5a5a5
BREAK
DCW 0xf6af,0xfbd2
; bl (0008ef3c); ResultCode(4, 0xf6af, 0xfbd2, Target(ADDRESS(&g_pTestCodes32[i*2], 0xFFFFFF00))); // 0xf7ff, 0xff80: -> 0xf6affbd2
BREAK
bl (00090300); ResultCode(4, 0xf6af, 0xba54, Target(ADDRESS(&g_pTestCodes32[i*2], 0xFFFFFC04))); // 0xf7ff, 0xff80: -> f6afba54 bl (00090300)
BREAK
push {r7,r11,lr}; ResultCode(4, 0xe92d, 0x4880); // 0xe92d, 0x4880: //
BREAK
BREAK
|TestCodes_end|
END

View File

@@ -0,0 +1,702 @@
/////////////////////////////////////////////////////////////////////////////
//
// Module: disas.cpp (disas.exe - Detours Test Program)
//
// Microsoft Research Detours Package
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
#define DETOURS_INTERNAL
#include <detours.h>
#include <stdio.h>
#include <stdlib.h>
///////////////////////////////////////////////////////////////////////// ARM.
//
#ifdef DETOURS_ARM
extern "C" BYTE TestCodes[];
void DumpMemoryFragment(PBYTE pbData, ULONG cbData, ULONG cbSpace)
{
ULONG n = 0;
if (cbData >= 4) {
printf("%04x%04x ", ((PUSHORT)pbData)[0], ((PUSHORT)pbData)[1]);
n += 4;
}
else if (cbData >= 2) {
printf("%04x ", *((PUSHORT)pbData));
n += 2;
}
for (; n < cbSpace; n++) {
if (n < cbData) {
printf("%02x", pbData[n]);
}
else {
printf(" ");
}
}
if (n < cbData) {
printf(".");
}
else {
printf(" ");
}
}
inline ULONG fetch_thumb_opcode(PBYTE pbCode)
{
ULONG Opcode = *(UINT16 *)&pbCode[0];
if (Opcode >= 0xe800) {
Opcode = (Opcode << 16) | *(UINT16 *)&pbCode[2];
}
return Opcode;
}
BOOL IsTerminate(PBYTE pbSrc)
{
ULONG opcode = fetch_thumb_opcode(pbSrc);
if ((opcode & 0xff87) == 0x4700) {
// bx r
return TRUE;
}
#if 0
if ((opcode & 0xfbf08f00) == 0xf2400c00) { // movw r12,#xxxx
return TRUE;
}
if ((opcode == 0xf8dcf000) { // ldr pc,[r12]
ULONG Immediate = ((opcode2 << 12) & 0xf7000000) |
((opcode2 << 1) & 0x08000000) |
((opcode2 << 16) & 0x00ff0000) |
((opcode >> 4) & 0x0000f700) |
((opcode >> 15) & 0x00000800) |
((opcode >> 0) & 0x000000ff);
PBYTE pbTarget = *(PBYTE *)Immediate;
if (detour_is_imported(pbCode, pbTarget)) {
PBYTE pbNew = *(PBYTE *)pbTarget;
DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew));
return pbNew;
}
}
}
}
#endif
return FALSE;
}
#endif // DETOURS_ARM
///////////////////////////////////////////////////////////////// X86 and X64.
//
#if defined(DETOURS_X86) || defined(DETOURS_X64)
extern "C" BYTE TestCodes[];
void DumpMemoryFragment(PBYTE pbData, ULONG cbData, ULONG cbSpace)
{
ULONG n = 0;
for (; n < cbSpace; n++) {
if (n < cbData) {
printf("%02x", pbData[n]);
}
else {
printf(" ");
}
}
if (n < cbData) {
printf(".");
}
else {
printf(" ");
}
}
BOOL IsTerminate(PBYTE pbSrc)
{
if ((0xC3 == pbSrc[0] && 0x00 == pbSrc[1]) || // bx lr
0xCB == pbSrc[0] || // RETF
0xC2 == pbSrc[0] || // RET dw
0xCA == pbSrc[0] || // RETF dw
0xEB == pbSrc[0] || // JMP ob
0xE9 == pbSrc[0] || // JMP ol
0xEA == pbSrc[0]) { // JMP ol
return TRUE;
}
if (0xff == pbSrc[0] && 0x25 == pbSrc[1]) // JMP [addr]
return TRUE;
return FALSE;
}
#endif // DETOURS_X86 || DETOURS_X64
/////////////////////////////////////////////////////////// X86, X64, and ARM.
//
#if defined(DETOURS_X86) || defined(DETOURS_X64) || defined(DETOURS_ARM)
struct BasicBlockLink
{
public:
BasicBlockLink * m_pNext;
PBYTE m_pbEntry;
PCHAR m_pszName;
public:
BasicBlockLink(PBYTE pbEntry, PCHAR pszName = NULL)
{
m_pNext = NULL;
m_pbEntry = pbEntry;
m_pszName = pszName;
*s_ppTail = this;
s_ppTail = &m_pNext;
}
BasicBlockLink * Next()
{
return m_pNext;
}
static BasicBlockLink * GetListHead()
{
return s_pHead;
}
protected:
static BasicBlockLink * s_pHead;
static BasicBlockLink ** s_ppTail;
};
BasicBlockLink * BasicBlockLink::s_pHead = NULL;
BasicBlockLink ** BasicBlockLink::s_ppTail = &BasicBlockLink::s_pHead;
static PBYTE s_pbBegin = NULL;
static PBYTE s_pbLimit = NULL;
int TestDetourCopyInstruction(PBYTE pbSrcInstruction, PCHAR pszFunction)
{
PBYTE pbSrc = pbSrcInstruction;
ULONG nIns = 0;
if (pszFunction) {
printf("%s:\n", pszFunction);
}
for (; nIns < 4096; nIns++) {
BYTE rbDst[128];
PVOID pbDstPool = (PVOID)(rbDst + sizeof(rbDst));
LONG lExtra = 0;
PVOID pbTarget = NULL;
ULONG cbStep = (ULONG)((PBYTE)DetourCopyInstruction(rbDst, &pbDstPool, pbSrc,
&pbTarget, &lExtra) - pbSrc);
printf(" %p:", pbSrc);
DumpMemoryFragment(rbDst, cbStep, 10);
printf(" ");
DumpMemoryFragment(rbDst, cbStep, 10);
if (pbTarget) {
if (pbTarget == DETOUR_INSTRUCTION_TARGET_DYNAMIC) {
printf(" Dynamic\n");
}
else {
printf(" %p%c\n", pbTarget,
(pbTarget >= s_pbBegin && pbTarget < s_pbLimit) ? ' ' : '!');
}
}
else {
printf("\n");
}
if (pbTarget && pbTarget != DETOUR_INSTRUCTION_TARGET_DYNAMIC) {
if (pbTarget > pbSrc &&
pbTarget >= s_pbBegin &&
pbTarget < s_pbLimit
) {
(void) new BasicBlockLink((PBYTE)pbTarget, NULL);
}
}
if (IsTerminate(pbSrc)) {
break;
}
pbSrc += cbStep;
}
return nIns;
}
BOOL CALLBACK ExportCallback(_In_opt_ PVOID pContext,
_In_ ULONG nOrdinal,
_In_opt_ LPCSTR pszName,
_In_opt_ PVOID pCode)
{
(void)pContext;
(void)nOrdinal;
(void)pCode;
(VOID) new BasicBlockLink((PBYTE)pCode, pszName ? pszName : "[NO NAME]");
return TRUE;
}
#endif // DETOURS_X86 || DETOURS_X64
//////////////////////////////////////////////////////////////////////// IA64.
//
#ifdef DETOURS_IA64
#pragma warning(disable: 4201) // ignore warning about unnamed sturcture in union.
void DumpHi(PBYTE pbData, ULONG cbData, ULONG cbSpace)
{
ULONG n = 0;
for (; n < cbSpace; n++) {
if (n < cbData) {
printf("%02x", pbData[(cbData - 1) - n]);
}
else {
printf(" ");
}
}
printf("\n");
}
struct DETOUR_IA64_BUNDLE_DISASSEMBLE : public DETOUR_IA64_BUNDLE
{
public:
void SetBrx(UINT64 raw)
{
SetBrl();
SetBrlImm(raw);
}
void Dis()
{
const char szUnitNames[17] = "?aimbflx?AIMBFLX";
printf("%p: ", data);
BYTE nTemplate = GetTemplate();
BYTE nInst0 = GetInst0();
BYTE nInst1 = GetInst1();
BYTE nInst2 = GetInst2();
BYTE nUnit0 = GetUnit0();
BYTE nUnit1 = GetUnit1();
BYTE nUnit2 = GetUnit2();
if (nUnit1 == L_UNIT) { // MLX instruction
UINT64 d2 = (
// 0x0000000000fffff0
((wide[1] & 0x00fffff000000000) >> 32) |
// 0x000000ffff000000
((wide[0] & 0xffff000000000000) >> 24) |
// 0x7fffff0000000000
((wide[1] & 0x00000000007fffff) << 40) |
// 0x8000000000000000
((wide[1] & 0x0800000000000000) << 4)
);
printf("%02x %c%01x %010I64lx %c%01x %016I64lx",
nTemplate,
szUnitNames[nUnit0], nInst0, GetData0(),
szUnitNames[nUnit2], nInst2, d2);
}
else {
printf("%02x %c%01x %010I64lx %c%01x %010I64lx %c%01x %010I64lx",
nTemplate,
szUnitNames[nUnit0], nInst0, GetData0(),
szUnitNames[nUnit1], nInst1, GetData1(),
szUnitNames[nUnit2], nInst2, GetData2());
}
if (IsBrl()) {
printf(" brl %p", GetBrlTarget());
}
else if (IsMovlGp()) {
printf(" movl gp=%p", GetMovlGp());
}
if ((wide[0] & 0xfffffc000603ffff) == 0x002024000200100b &&
wide[1] == 0x0004000000203008) {
ULONG64 offset =
((wide[0] & 0x0000000001fc0000) >> 18) | // imm7b
((wide[0] & 0x000001ff00000000) >> 25) | // imm9d
((wide[0] & 0x00000000f8000000) >> 11); // imm5c
if (wide[0] & 0x0000020000000000) {
offset |= 0xffffffffffe00000;
}
printf(" imm=%016I64lx", offset);
}
printf("\n");
}
};
//////////////////////////////////////////////////////////////////////////////
//
BOOL CALLBACK ExportCallbackIA64(_In_opt_ PVOID pContext,
_In_ ULONG nOrdinal,
_In_opt_ LPCSTR pszName,
_In_opt_ PVOID pCode)
{
(void)pContext;
(void)nOrdinal;
DETOUR_IA64_BUNDLE_DISASSEMBLE *pb = *(DETOUR_IA64_BUNDLE_DISASSEMBLE **)pCode;
DETOUR_IA64_BUNDLE temp;
if (!pb[0].Copy(&temp)) {
printf("%s:\n ", pszName ? pszName : "[NO NAME]");
pb[0].Dis();
}
return TRUE;
}
#if 0
void TestBoth()
{
LPVOID pvBase = VirtualAlloc((PBYTE)0x800000000, 0x10000,
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
DETOUR_IA64_BUNDLE *pbBase = (DETOUR_IA64_BUNDLE *)pvBase;
DETOUR_IA64_BUNDLE *pb = pbBase;
printf("TestBoth:\n");
for (UINT64 i = 0x10; i < 0x8000000000000000; i <<= 1) {
pb->SetMovlGp(i);
if (pb->GetMovlGp() != i) {
printf("Error in MovlGp!\n");
return;
}
pb++;
pb->SetBrl(i);
if (pb->GetBrlEip() != i) {
printf("Error in Brl!\n");
return;
}
pb++;
}
for (UINT64 i = (UINT64)(INT64)-0x10; i > 0; i <<= 1) {
pb->SetMovlGp(i);
if (pb->GetMovlGp() != i) {
printf("Error in MovlGp!\n");
return;
}
pb++;
pb->SetBrl(i);
if (pb->GetBrlEip() != i) {
printf("Error in Brl!\n");
return;
}
pb++;
}
printf("u %p %p\n", pbBase, pb);
}
#endif
#endif // DETOURS_IA64
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmdShow)
{
(void)hprev;
(void)hinst;
(void)lpszCmdLine;
(void)nCmdShow;
// Bug report, but it works here.
// 07ff8`4b783054 49ba 70b3d93a d40fb998 mov r10,98B90FD43AD9B370h
//
{
static const UCHAR mov_r10_imm64[] = {0x49, 0xba, 1, 2, 3, 4, 5, 6, 7, 8 };
PVOID const after = DetourCopyInstructionX64(0, 0, const_cast<PUCHAR>(mov_r10_imm64), 0, 0);
if (after != &mov_r10_imm64 + 1)
{
printf("mov_r10_imm64 failed, expected:%p vs. got:%p\n", &mov_r10_imm64 + 1, after);
if (IsDebuggerPresent())
{
__debugbreak();
DetourCopyInstructionX64(0, 0, const_cast<PUCHAR>(mov_r10_imm64), 0, 0);
}
return 1;
}
}
#ifdef DETOURS_IA64
// First we check the pre-canned TestCodes from disasm.asm
//
PBYTE pbTest = *(PBYTE*)WinMain;
for (;; pbTest += 16) {
DETOUR_IA64_BUNDLE_DISASSEMBLE *pb = (DETOUR_IA64_BUNDLE_DISASSEMBLE *)pbTest;
pb->Dis();
if (pbTest[0] == 0xff) {
break;
}
DumpHi(pbTest, 16, 16);
}
#if 0
printf("\n\n");
DETOUR_IA64_BUNDLE_DISASSEMBLE *pb = (DETOUR_IA64_BUNDLE_DISASSEMBLE *)pbTest;
DETOUR_IA64_BUNDLE_DISASSEMBLE *pbBeg = pb;
DWORD dwOld;
VirtualProtect(pb, 0x2000, PAGE_EXECUTE_READWRITE, &dwOld);
printf("%p: (%d)\n", pb, sizeof(pb));
pb++;
printf("%p: (%d)\n", pb, sizeof(pb));
pb++; pb->SetBrx(0);
pb++; pb->SetBrx(0);
pb++; pb->SetBrx(0);
pb++; pb->SetBrx(0xffffffffffffffff);
pb++; pb->SetBrx(0x0fffffffffffffff);
pb++; pb->SetBrx(0x00ffffffffffffff);
pb++; pb->SetBrx(0x000fffffffffffff);
pb++; pb->SetBrx(0x0000ffffffffffff);
pb++; pb->SetBrx(0x00000fffffffffff);
pb++; pb->SetBrx(0x000000ffffffffff);
pb++; pb->SetBrx(0x0000000fffffffff);
pb++; pb->SetBrx(0x00000000ffffffff);
pb++; pb->SetBrx(0x000000000fffffff);
pb++; pb->SetBrx(0x0000000000ffffff);
pb++; pb->SetBrx(0x00000000000fffff);
pb++; pb->SetBrx(0x000000000000ffff);
pb++; pb->SetBrx(0x0000000000000fff);
pb++; pb->SetBrx(0x00000000000000ff);
pb++; pb->SetBrx(0x000000000000000f);
pb++; pb->SetBrx(0x0000000000000000);
pb++; pb->SetBrx(0xffffffffffffffff);
pb++; pb->SetBrx(0xffffffffffffffff);
pb->SetInst0(0xff);
pb->SetData0(0xffffffffffffffff);
printf("%p:\n", pb);
DETOUR_IA64_BUNDLE_DISASSEMBLE *pbEnd = pb;
for (pb = pbBeg; pb < pbEnd; pb++) {
printf(" %p: ", pb);
DumpHi((BYTE*)pb, 16, 16);
}
#endif
#if 1
{
// Then we check all of the code we can find in user32.dll
//
printf("\n");
HINSTANCE hInst = LoadLibraryA("user32.dll");
printf("Loaded: user32.dll: %p\n", hInst);
PBYTE pbEntry = (PBYTE)DetourGetEntryPoint(hInst);
printf("Entry: %p\n", pbEntry);
ExportCallbackIA64(NULL, 0, "[Entry]", pbEntry);
DetourEnumerateExports(hInst, NULL, ExportCallbackIA64);
}
{
// Then we check all of the code we can find in opengl32.dll
//
printf("\n");
HINSTANCE hInst = LoadLibraryA("opengl32.dll");
printf("Loaded: opengl32.dll: %p\n", hInst);
PBYTE pbEntry = (PBYTE)DetourGetEntryPoint(hInst);
printf("Entry: %p\n", pbEntry);
ExportCallbackIA64(NULL, 0, "[Entry]", pbEntry);
DetourEnumerateExports(hInst, NULL, ExportCallbackIA64);
}
printf("\n");
for (HINSTANCE hInst = NULL; (hInst = DetourEnumerateModules(hInst)) != NULL;) {
CHAR szModuleName[512];
GetModuleFileNameA(hInst, szModuleName,
sizeof(szModuleName)/sizeof(szModuleName[0]));
printf("%p : %s\n", hInst, szModuleName);
DetourEnumerateExports(hInst, NULL, ExportCallbackIA64);
}
printf("\n");
#endif
#if 0
TestBoth();
#endif
#endif // DETOURS_IA64
#if defined(DETOURS_X64) || defined(DETOURS_X86)
// First we check the pre-canned TestCodes from disasm.asm
//
PBYTE pbBegin = (PBYTE)DetourCodeFromPointer(TestCodes, NULL);
printf("%p:\n", pbBegin);
for (PBYTE pbTest = pbBegin;;) {
if (pbTest[0] != 0xcc) { // int 3
printf("%08lx ", (ULONG)(pbTest - pbBegin));
DumpMemoryFragment(pbTest, 8, 8);
printf("\n");
printf("failed on last.\n");
return 1;
}
pbTest++;
if (pbTest[0] == 0x70 || pbTest[0] == 0x71) {
printf("[%p]:\n", pbTest);
}
BYTE rbDst[128];
PVOID pbDstPool = (PVOID)(rbDst + sizeof(rbDst));
LONG lExtra = 0;
PVOID pbTarget = NULL;
PBYTE pbNext = (PBYTE)DetourCopyInstruction(rbDst, &pbDstPool, pbTest,
&pbTarget, &lExtra);
LONG cbTest = (LONG)(pbNext - pbTest);
printf("%08lx ", (ULONG)(pbTest - pbBegin));
DumpMemoryFragment(pbTest, cbTest, 12);
printf("[%16p] ", pbTarget);
DumpMemoryFragment(rbDst, cbTest + lExtra, 11);
printf("\n");
if (pbTest[cbTest] != 0xcc) {
printf("failed!\n");
return 1;
}
pbTest += cbTest;
if (pbTest[0] == 0xcc && pbTest[1] == 0xcc) {
break;
}
}
#if 0
// Then we check all of the code we can find in user32.dll
//
HINSTANCE hInst = LoadLibraryA("user32.dll");
printf("Loaded: user32.dll: %p\n", hInst);
s_pbBegin = (PBYTE)hInst;
s_pbLimit = s_pbBegin + DetourGetModuleSize(hInst);
PBYTE pbEntry = DetourGetEntryPoint(hInst);
(VOID) new BasicBlockLink(pbEntry, "user32.dll");
DetourEnumerateExports(hInst, NULL, ExportCallback);
ULONG nIns = 0;
for (BasicBlockLink *pLink = BasicBlockLink::GetListHead();
pLink; pLink = pLink->Next()) {
nIns += TestDetourCopyInstruction(pLink->m_pbEntry, pLink->m_pszName);
if (nIns > 100000) {
break;
}
}
printf("Disassembled %d instructions.\n", nIns);
#endif
#endif // DETOURS_X86 || DETOURS_X64
#ifdef DETOURS_ARM
// Create an output buffer and fill it with debugbreaks.
//
PBYTE pbBuffer
= (PBYTE)VirtualAlloc(NULL, 0x400, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
for (PBYTE pbOut = pbBuffer; pbOut < pbBuffer + 0x400;) {
*pbOut++ = 0xfe;
*pbOut++ = 0xde;
}
PBYTE pbDst = pbBuffer;
PVOID pvDstPool = (PVOID)(pbBuffer + 0x400);
// First we check the pre-canned TestCodes from disasm.asm
//
PBYTE pbBegin = (PBYTE)DetourCodeFromPointer(TestCodes, NULL);
printf("%p: (TestCodes %p) => %p\n", pbBegin, TestCodes, pbBuffer);
for (PBYTE pbSrc = pbBegin;;) {
if (pbSrc[0] != 0xfe && pbSrc[1] != 0xde) { // BREAK
printf("%08x ", pbSrc - pbBegin);
DumpMemoryFragment(pbSrc, 8, 8);
printf("\n");
printf("failed on last.\n");
return 1;
}
pbSrc += 2;
*pbDst++ = 0xfe;
*pbDst++ = 0xde;
if ((pbSrc[0] == 0x00 && pbSrc[1] == 0xbf) && // NOP
(pbSrc[2] != 0xfe && pbSrc[3] != 0xde)) { // BREAK
// Skip over a single NOP so we can test alignment.
pbSrc += 2;
}
if ((pbSrc[0] == 0x00 && pbSrc[1] == 0xbf) && // NOP
(pbSrc[2] != 0xfe && pbSrc[3] != 0xde)) { // BREAK
// If there is a second NOP, then we insert alignment.
pbSrc += 2;
*pbDst++ = 0x00;
*pbDst++ = 0xbf;
}
LONG lExtra = 0;
PVOID pbTarget = NULL;
PBYTE pbNext = (PBYTE)DetourCopyInstruction(pbDst, &pvDstPool, pbSrc, &pbTarget, &lExtra);
LONG cbTest = (LONG)(pbNext - pbSrc);
printf("%08x ", pbSrc - pbBegin);
DumpMemoryFragment(pbSrc, cbTest, 4);
printf("[%8p] ", pbTarget);
DumpMemoryFragment(pbDst, cbTest + lExtra, 16);
printf("\n");
if (pbSrc[cbTest] != 0xfe || pbSrc[cbTest+1] != 0xde) {
printf("%p: failed! (pbSrc[n]=%02x, pbSrc[n+1]=%02x\n",
pbSrc,
pbSrc[cbTest], pbSrc[cbTest+1]);
__debugbreak();
pbNext = (PBYTE)DetourCopyInstruction(pbDst, &pvDstPool, pbSrc, &pbTarget, &lExtra);
cbTest = (LONG)(pbNext - pbSrc);
return 1;
}
pbDst += cbTest + lExtra;
pbSrc += cbTest;
if (pbSrc[0] == 0xfe && pbSrc[1] == 0xde &&
pbSrc[2] == 0xfe && pbSrc[3] == 0xde) {
break;
}
}
#if 0
// Then we check all of the code we can find in user32.dll
//
HINSTANCE hInst = LoadLibraryA("user32.dll");
printf("Loaded: user32.dll: %p\n", hInst);
s_pbBegin = (PBYTE)hInst;
s_pbLimit = s_pbBegin + DetourGetModuleSize(hInst);
PBYTE pbEntry = DetourGetEntryPoint(hInst);
(VOID) new BasicBlockLink(pbEntry, "user32.dll");
DetourEnumerateExports(hInst, NULL, ExportCallback);
ULONG nIns = 0;
for (BasicBlockLink *pLink = BasicBlockLink::GetListHead();
pLink; pLink = pLink->Next()) {
nIns += TestDetourCopyInstruction(pLink->m_pbEntry, pLink->m_pszName);
if (nIns > 100000) {
break;
}
}
printf("Disassembled %d instructions.\n", nIns);
#endif
#endif // DETOURS_ARM
return 0;
}
//
///////////////////////////////////////////////////////////////// End of File.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
/////////////////////////////////////////////////////////////////////////////
//
// Detours Test Program (x86.asm of disas.exe)
//
// Microsoft Research Detours Package
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
static int value = 0;
extern "C" void TestCodes()
{
value++;
}

View File

@@ -0,0 +1,520 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Detours Test Program (x64.asm/disas.exe)
;;
;; Microsoft Research Detours Package
;;
;; Copyright (c) Microsoft Corporation. All rights reserved.
;;
.xlist
.list
.code
PUBLIC TestCodes
_TEXT SEGMENT
TestCodes PROC
begin:
faraway:
int 3
nop
int 3
db 066h,090h ; // 2-byte NOP.
int 3
db 00fh, 01fh, 000h ; // 3-byte NOP.
int 3
db 00fh, 01fh, 040h, 000h ; // 4-byte NOP.
int 3
db 00fh, 01fh, 044h, 000h, 000h ; // 5-byte NOP.
int 3
db 066h, 00fh, 01fh, 044h, 000h, 000h ; // 6-byte NOP.
int 3
db 00fh, 01fh, 080h, 000h, 000h, 000h, 000h ; // 7-byte NOP.
int 3
db 00fh, 01fh, 084h, 000h, 000h, 000h, 000h, 000h ; // 8-byte NOP.
int 3
db 066h, 00fh, 01fh, 084h, 000h, 000h, 000h, 000h, 000h ; // 9-byte NOP.
int 3
mov rax, cr8
int 3
mov rcx, cr8
int 3
mov rdx, cr8
int 3
mov rbx, cr8
int 3
mov rsp, cr8
int 3
mov rbp, cr8
int 3
mov rsi, cr8
int 3
mov rdi, cr8
int 3
mov r8, cr8
int 3
mov r9, cr8
int 3
mov r10, cr8
int 3
mov r11, cr8
int 3
mov r12, cr8
int 3
mov r13, cr8
int 3
mov r14, cr8
int 3
mov r15, cr8
int 3
mov cr8, rax
int 3
mov cr8, rcx
int 3
mov cr8, rdx
int 3
mov cr8, rbx
int 3
mov cr8, rsp
int 3
mov cr8, rbp
int 3
mov cr8, rsi
int 3
mov cr8, rdi
int 3
mov cr8, r8
int 3
mov cr8, r9
int 3
mov cr8, r10
int 3
mov cr8, r11
int 3
mov cr8, r12
int 3
mov cr8, r13
int 3
mov cr8, r14
int 3
mov cr8, r15
int 3
xor rax, rax
int 3
xor rcx, rcx
int 3
xor rdx, rdx
int 3
xor rbx, rbx
int 3
xor rsp, rsp
int 3
xor rbp, rbp
int 3
xor rsi, rsi
int 3
xor rdi, rdi
int 3
xor r8, r8
int 3
xor r9, r9
int 3
xor r10, r10
int 3
xor r11, r11
int 3
xor r12, r12
int 3
xor r13, r13
int 3
xor r14, r14
int 3
xor r15, r15
int 3
jmp rax
int 3
jmp rbx
int 3
jmp rcx
int 3
jmp rdx
int 3
push rax
int 3
push rbx
int 3
push rcx
int 3
push rdx
int 3
push 0
int 3
pop rax
int 3
pop rbx
int 3
pop rcx
int 3
pop rdx
int 3
mov rax,[value]
int 3
sub rsp,0418h
int 3
mov [rsp+0410h],rbx
int 3
mov [rsp+0408h],rsi
int 3
mov [rsp+0400h],rdi
int 3
mov [rsp+03f8h],r12
int 3
mov [rsp+03f0h],r13
int 3
mov [rsp+03e8h],r14
int 3
mov [rsp+03e0h],r15
int 3
add [rax],al ; 0000
int 3
add [rcx],al ; 0001
int 3
add [rbx],al ; 0003
int 3
add [rax+rax],al ; 000400
int 3
add [rdi],al ; 0007
int 3
add [rax],cl ; 0008
int 3
add [rdi],cl ; 000f
int 3
add [rax],dl ; 0010
int 3
add [rdi],bl ; 001f
int 3
add [rax],ah ; 0020
int 3
add [rdi],bh ; 003f
int 3
add [rax+03bh],cl ; 00483b
int 3
add [rdi],bh ; 007f00
int 3
add [rax+040000000h],al ; 008000000040
int 3
add bh,bh ; 00ff
int 3
add [rax],eax ; 0100
int 3
add al,[rax] ; 0200
int 3
add eax,06603ebc3h ; 05c3eb0366
int 3
syscall ; 0f05
int 3
prefetchw byte ptr [rcx] ; 0f0d09
int 3
prefetchnta byte ptr [rcx] ; 0f1801
int 3
prefetchnta byte ptr [rax+rdx] ; 0f180410
int 3
jb again ; 0f8247070000
int 3
jnb again ; 0f8306050000
int 3
je again ; 0f8432010000
int 3
jne again ; 0f8508010000
int 3
jnbe again ; 0f878a000000
int 3
ldmxcsr dword ptr [rcx+034h] ; 0fae5134
int 3
stmxcsr dword ptr [rcx+034h] ; 0fae5934
int 3
and ecx,[rdx+rbx*4] ; 230c9a
int 3
xor eax,eax ; 33c0
int 3
xor ecx,ecx ; 33c9
int 3
xor edx,ecx ; 33d1
int 3
xor edx,edx ; 33d2
int 3
add r10d,010001h ; 4181c201000100
int 3
and r11d,0ffffh ; 4181e3ffff0000
int 3
mov eax,r8d ; 418bc0
int 3
mov byte ptr [r11],00h ; 41c60300
int 3
call qword ptr [r9+030h] ; 41ff5130
int 3
call qword ptr [r9+r8*8] ; 43ff14c1
int 3
mov [rcx+034h],r8d ; 44894134
int 3
mov [rsp+030h],r9d ; 44894c2430
int 3
mov r8d,[rcx] ; 448b01
int 3
mov r9d,[rcx] ; 448b09
int 3
mov r8d,[rax+058h] ; 448b4058
int 3
mov r8d,[rsp+02ch] ; 448b44242c
int 3
mov r8d,eax ; 448bc0
int 3
mov r8d,edx ; 448bc2
int 3
xor r8b,r8b ; 4532c0
int 3
mov r9d,r8d ; 458bc8
int 3
lea r11d,[r9+rax] ; 458d1c01
int 3
add rdx,rcx ; 4803d1
int 3
or rsi,rdx ; 480bf2
int 3
movnti [rcx],rax ; 480fc301
int 3
and rax,0fe000000h ; 4825000000fe
int 3
sub rax,rcx ; 482bc1
int 3
sub rdx,rcx ; 482bd1
int 3
cmp rdi,rbp ; 483bfd
int 3
push rbp ; 4855
int 3
add rcx,03d0h ; 4881c1d0030000
int 3
add rsp,0c8h ; 4881c4c8000000
int 3
and rdx,0fe000000h ; 4881e2000000fe
int 3
sub rsp,0c8h ; 4881ecc8000000
int 3
sub rsp,03d0h ; 4881ecd0030000
int 3
add rax,040h ; 4883c040
int 3
add rcx,08h ; 4883c108
int 3
add rcx,040h ; 4883c140
int 3
add rsp,08h ; 4883c408
int 3
add rsi,09h ; 4883c609
int 3
add rdi,01h ; 4883c701
int 3
and rcx,0f8h ; 4883e1f8
int 3
sub rax,040h ; 4883e840
int 3
sub rdx,08h ; 4883ea08
int 3
sub rdx,040h ; 4883ea40
int 3
sub rsp,08h ; 4883ec08
int 3
sub rsi,08h ; 4883ee08
int 3
sub rdi,01h ; 4883ef01
int 3
test rax,rax ; 4885c0
int 3
test rdx,rdx ; 4885d2
int 3
mov [rsp],rax ; 48890424
int 3
mov [rsp],rbp ; 48892c24
int 3
mov [rsp],rsi ; 48893424
int 3
mov [rsp],rdi ; 48893c24
int 3
mov [rcx+08h],rax ; 48894108
int 3
mov [rcx+078h],rax ; 48894178
int 3
mov [rcx-08h],rax ; 488941f8
int 3
mov [rsp+018h],rax ; 4889442418
int 3
mov [rcx+010h],rdx ; 48895110
int 3
mov [rsp+08h],rbx ; 48895c2408
int 3
mov [rsp+018h],rsi ; 4889742418
int 3
mov [rsp+08h],rdi ; 48897c2408
int 3
mov [rsp+010h],rdi ; 48897c2410
int 3
mov [rcx+098h],rax ; 48898198000000
int 3
mov [rcx+080h],rcx ; 48898980000000
int 3
mov [rcx+088h],rdx ; 48899188000000
int 3
mov [rcx+090h],rbx ; 48899990000000
int 3
mov [rcx+0a0h],rbp ; 4889a9a0000000
int 3
mov [rcx+0a8h],rsi ; 4889b1a8000000
int 3
mov [rcx+0b0h],rdi ; 4889b9b0000000
int 3
mov rax,[rcx] ; 488b01
int 3
mov rax,[rcx+rdx] ; 488b0411
int 3
mov rax,[value] ; 488b05318c0100
int 3
mov rcx,[rsp] ; 488b0c24
int 3
mov rsi,[rsp] ; 488b3424
int 3
mov rdi,[rsp] ; 488b3c24
int 3
mov rax,[rax+018h] ; 488b4018
int 3
mov rax,[rcx+078h] ; 488b4178
int 3
mov rax,[rdx+020h] ; 488b4220
int 3
mov rax,[rsp+08h] ; 488b442408
int 3
mov rcx,[rcx+08h] ; 488b4908
int 3
mov rcx,[rsp+020h] ; 488b4c2420
int 3
mov rdx,[rsp+08h] ; 488b542408
int 3
mov rdi,[rsp+08h] ; 488b7c2408
int 3
mov rax,[rcx+098h] ; 488b8198000000
int 3
mov rax,[rcx+0f8h] ; 488b81f8000000
int 3
cmp ebx,0 ;
int 3
cmp rbx,0 ;
int 3
cmp byte ptr [value],77h ; 803d........77
int 3
cmp dword ptr [value],77h ; 833d........77
int 3
cmp qword ptr [value],77h ; 48833d........77
int 3
cmp dword ptr [value],77777777h ; 813d........77777777
int 3
cmp qword ptr [value],77777777h ; 48813d........77777777
int 3
nearby:
jo nearby ; 70xx
int 3
jno nearby ; 71xx
int 3
jb nearby ; 72xx
int 3
jae nearby ; 73xx
int 3
je nearby ; 74xx
int 3
jne nearby ; 75xx
int 3
jbe nearby ; 76xx
int 3
ja nearby ; 77xx
int 3
js nearby ; 78xx
int 3
jns nearby ; 79xx
int 3
jp nearby ; 7axx
int 3
jnp nearby ; 7bxx
int 3
jl nearby ; 7cxx
int 3
jge nearby ; 7dxx
int 3
jle nearby ; 7exx
int 3
jg nearby ; 7fxx
int 3
jmp nearby ; ebxx
int 3
jo faraway ; 0f80xxxxxxxx
int 3
jno faraway ; 0f81xxxxxxxx
int 3
jb faraway ; 0f82xxxxxxxx
int 3
jae faraway ; 0f83xxxxxxxx
int 3
je faraway ; 0f84xxxxxxxx
int 3
jne faraway ; 0f85xxxxxxxx
int 3
jbe faraway ; 0f86xxxxxxxx
int 3
ja faraway ; 0f87xxxxxxxx
int 3
js faraway ; 0f88xxxxxxxx
int 3
jns faraway ; 0f89xxxxxxxx
int 3
jp faraway ; 0f8axxxxxxxx
int 3
jnp faraway ; 0f8bxxxxxxxx
int 3
jl faraway ; 0f8cxxxxxxxx
int 3
jge faraway ; 0f8dxxxxxxxx
int 3
jle faraway ; 0f8exxxxxxxx
int 3
jg faraway ; 0f8fxxxxxxxx
int 3
jmp faraway ; e9xxxxxxxx
int 3
lea rax,[rsp] ; 488d0424
int 3
mov rcx,0BADC0DEBA5Eh ; 48b95ebadec0ad0b0000
int 3
cmp rax,rcx ; 483bc1
int 3
sub rsp, 28h
int 3
add rsp,28h
int 3
ret
int 3
;; The list is terminated by two "int 3" in a row.
again:
int 3
int 3
TestCodes ENDP
value QWORD 0
_TEXT ENDS
END

View File

@@ -0,0 +1,184 @@
/////////////////////////////////////////////////////////////////////////////
//
// Detours Test Program (x86.asm of disas.exe)
//
// Microsoft Research Detours Package
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
static int value = 0;
extern "C" void __declspec(naked) TestCodes()
{
__asm {
// Each instruction is proceeded by an "int 3".
faraway:
int 3;
nop; // 1-byte NOP.
int 3;
_emit 0x66; // 2-byte NOP.
_emit 0x90;
int 3;
_emit 0x0f; // 3-byte NOP.
_emit 0x1f;
_emit 0x00;
int 3;
_emit 0x0f; // 4-byte NOP.
_emit 0x1f;
_emit 0x40;
_emit 0x00;
int 3;
_emit 0x0f; // 5-byte NOP.
_emit 0x1f;
_emit 0x44;
_emit 0x00;
_emit 0x00;
int 3;
_emit 0x66; // 6-byte NOP.
_emit 0x0f;
_emit 0x1f;
_emit 0x44;
_emit 0x00;
_emit 0x00;
int 3;
_emit 0x0f; // 7-byte NOP.
_emit 0x1f;
_emit 0x80;
_emit 0x00;
_emit 0x00;
_emit 0x00;
_emit 0x00;
int 3;
_emit 0x0f; // 8-byte NOP.
_emit 0x1f;
_emit 0x84;
_emit 0x00;
_emit 0x00;
_emit 0x00;
_emit 0x00;
_emit 0x00;
int 3;
_emit 0x66; // 9-byte NOP.
_emit 0x0f;
_emit 0x1f;
_emit 0x84;
_emit 0x00;
_emit 0x00;
_emit 0x00;
_emit 0x00;
_emit 0x00;
int 3;
mov ecx, eax;
int 3;
mov ebx, 0ffff000eh;
int 3;
call ebx;
int 3;
call dword ptr [eax];
int 3;
call dword ptr [ebx];
int 3;
call dword ptr [ecx];
int 3;
call dword ptr [edx];
int 3;
jmp dword ptr [eax];
int 3;
jmp dword ptr [ebx];
int 3;
jmp dword ptr [ecx];
int 3;
jmp dword ptr [edx];
int 3;
call ecx;
int 3;
call eax;
int 3;
mov ebx, 0ffff000eh;
int 3;
push eax;
int 3;
call ebx;
int 3;
cmp ebx, 0;
int 3;
cmp byte ptr [value], 77h;
int 3;
cmp dword ptr [value], 77h;
int 3;
cmp dword ptr [value], 77777777h;
nearby:
int 3
jo nearby ; 70xx
int 3
jno nearby ; 71xx
int 3
jb nearby ; 72xx
int 3
jae nearby ; 73xx
int 3
je nearby ; 74xx
int 3
jne nearby ; 75xx
int 3
jbe nearby ; 76xx
int 3
ja nearby ; 77xx
int 3
js nearby ; 78xx
int 3
jns nearby ; 79xx
int 3
jp nearby ; 7axx
int 3
jnp nearby ; 7bxx
int 3
jl nearby ; 7cxx
int 3
jge nearby ; 7dxx
int 3
jle nearby ; 7exx
int 3
jg nearby ; 7fxx
int 3
jo faraway ; 0f80xx
int 3
jno faraway ; 0f81xx
int 3
jb faraway ; 0f82xx
int 3
jae faraway ; 0f83xx
int 3
je faraway ; 0f84xx
int 3
jne faraway ; 0f85xx
int 3
jbe faraway ; 0f86xx
int 3
ja faraway ; 0f87xx
int 3
js faraway ; 0f88xx
int 3
jns faraway ; 0f89xx
int 3
jp faraway ; 0f8axx
int 3
jnp faraway ; 0f8bxx
int 3
jl faraway ; 0f8cxx
int 3
jge faraway ; 0f8dxx
int 3
jle faraway ; 0f8exx
int 3
jg faraway ; 0f8fxx
// The list is terminated by two "int 3" in a row.
int 3;
int 3;
ret;
}
}