1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
/* $Id: tstLdrDisasmTest.cpp $ */
/** @file
* IPRT - RTLdr test object.
*
* We use precompiled versions of this object for testing all the loaders.
*
* This is not supposed to be pretty or usable code, just something which
* make life difficult for the loader.
*/
/*
* Copyright (C) 2006-2019 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*********************************************************************************************************************************
* Header Files *
*********************************************************************************************************************************/
#include <VBox/dis.h>
#include <VBox/disopcode.h>
#include <VBox/sup.h>
#include <iprt/string.h>
#if defined(IN_RING0)
# define MY_PRINTF(a) SUPR0Printf a
#else
# define MY_PRINTF(a) do {} while (0)
#endif
/*********************************************************************************************************************************
* Global Variables *
*********************************************************************************************************************************/
/* 32-bit code */
static const uint8_t g_ab32BitCode[] =
{
0x55, // 1000ab50 55 push ebp
0x8b,0xec, // 1000ab51 8bec mov ebp,esp
0x8b,0x45,0x08, // 1000ab53 8b4508 mov eax,dword ptr [ebp+8]
0x81,0x38,0x07,0x07,// 1000ab56 813807076419 cmp dword ptr [eax],19640707h
0x64,0x19,
0x75,0x09, // 1000ab5c 7509 jne kLdr!kLdrModMap+0x17 (1000ab67)
0x8b,0x4d,0x08, // 1000ab5e 8b4d08 mov ecx,dword ptr [ebp+8]
0x83,0x79,0x2c,0x00,// 1000ab61 83792c00 cmp dword ptr [ecx+2Ch],0
0x75,0x07, // 1000ab65 7507 jne kLdr!kLdrModMap+0x1e (1000ab6e)
0xb8,0xc0,0x68,0x06,// 1000ab67 b8c0680600 mov eax,668C0h
0x00,
0xeb,0x14, // 1000ab6c eb14 jmp kLdr!kLdrModMap+0x32 (1000ab82)
0x33,0xd2, // 1000ab6e 33d2 xor edx,edx
0x75,0xe1, // 1000ab70 75e1 jne kLdr!kLdrModMap+0x3 (1000ab53)
0x8b,0x45,0x08, // 1000ab72 8b4508 mov eax,dword ptr [ebp+8]
0x50, // 1000ab75 50 push eax
0x8b,0x4d,0x08, // 1000ab76 8b4d08 mov ecx,dword ptr [ebp+8]
0x8b,0x51,0x2c, // 1000ab79 8b512c mov edx,dword ptr [ecx+2Ch]
0xff,0x52,0x3c, // 1000ab7c ff523c call dword ptr [edx+3Ch]
0x83,0xc4,0x04, // 1000ab7f 83c404 add esp,4
0x5d, // 1000ab82 5d pop ebp
0xc3, // 1000ab83 c3 ret
0xcc
};
/**
* @callback_method_impl{FNDISREADBYTES}
*/
static DECLCALLBACK(int) DisasmTest1ReadCode(PDISCPUSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
{
size_t cb = cbMaxRead;
if (cb + pDis->uInstrAddr + offInstr > sizeof(g_ab32BitCode))
cb = cbMinRead;
memcpy(&pDis->abInstr[offInstr], &g_ab32BitCode[pDis->uInstrAddr + offInstr], cb);
pDis->cbCachedInstr = offInstr + (uint8_t)cb;
return VINF_SUCCESS;
}
/*
* Use an inline function here just to test '__textcoal_nt' sections on darwin.
*/
inline int MyDisasm(uintptr_t CodeIndex, PDISCPUSTATE pCpu, uint32_t *pcb)
{
uint32_t cb;
int rc = DISInstrWithReader(CodeIndex, DISCPUMODE_32BIT, DisasmTest1ReadCode, 0, pCpu, &cb);
*pcb = cb;
MY_PRINTF(("DISCoreOneEx -> rc=%d cb=%d Cpu: bOpCode=%#x pCurInstr=%p (42=%d)\n", \
rc, cb, pCpu->bOpCode, pCpu->pCurInstr, 42)); \
return rc;
}
extern "C" DECLEXPORT(int) DisasmTest1(void)
{
DISCPUSTATE Cpu;
uintptr_t CodeIndex = 0;
uint32_t cb;
int rc;
MY_PRINTF(("DisasmTest1: %p\n", &DisasmTest1));
#if defined(IN_RING0)
MY_PRINTF(("GIP: g_pSUPGlobalInfoPage=%p\n", g_pSUPGlobalInfoPage));
MY_PRINTF(("GIP: magic=%#x version=%#x mode=%d cCpus=%d\n", g_pSUPGlobalInfoPage->u32Magic, g_pSUPGlobalInfoPage->u32Version,
g_pSUPGlobalInfoPage->u32Mode, g_pSUPGlobalInfoPage->cCpus));
if (g_pSUPGlobalInfoPage->u32Magic != SUPGLOBALINFOPAGE_MAGIC)
return 0xc001;
if (g_pSUPGlobalInfoPage->u32Version != SUPGLOBALINFOPAGE_VERSION)
return 0xc002;
if (g_pSUPGlobalInfoPage->u32Mode != SUPGIPMODE_INVARIANT_TSC)
return 0xc003;
if (g_pSUPGlobalInfoPage->cCpus != 42)
return 0xc004;
#endif
memset(&Cpu, 0, sizeof(Cpu));
#define DISAS_AND_CHECK(cbInstr, enmOp) \
do { \
rc = MyDisasm(CodeIndex, &Cpu, &cb); \
if (RT_FAILURE(rc)) \
return CodeIndex | 0xf000; \
if (Cpu.pCurInstr->uOpcode != (enmOp)) \
return CodeIndex| 0xe000; \
if (cb != (cbInstr)) \
return CodeIndex | 0xd000; \
CodeIndex += cb; \
} while (0)
DISAS_AND_CHECK(1, OP_PUSH);
DISAS_AND_CHECK(2, OP_MOV);
DISAS_AND_CHECK(3, OP_MOV);
DISAS_AND_CHECK(6, OP_CMP);
DISAS_AND_CHECK(2, OP_JNE);
DISAS_AND_CHECK(3, OP_MOV);
DISAS_AND_CHECK(4, OP_CMP);
DISAS_AND_CHECK(2, OP_JNE);
DISAS_AND_CHECK(5, OP_MOV);
DISAS_AND_CHECK(2, OP_JMP);
DISAS_AND_CHECK(2, OP_XOR);
DISAS_AND_CHECK(2, OP_JNE);
DISAS_AND_CHECK(3, OP_MOV);
DISAS_AND_CHECK(1, OP_PUSH);
DISAS_AND_CHECK(3, OP_MOV);
DISAS_AND_CHECK(3, OP_MOV);
DISAS_AND_CHECK(3, OP_CALL);
DISAS_AND_CHECK(3, OP_ADD);
DISAS_AND_CHECK(1, OP_POP);
DISAS_AND_CHECK(1, OP_RETN);
DISAS_AND_CHECK(1, OP_INT3);
return rc;
}
|