VirtualBox

source: vbox/trunk/src/VBox/Disassembler/testcase/tstDisasm-1.cpp@ 100802

Last change on this file since 100802 was 99775, checked in by vboxsync, 19 months ago

*: Mark functions as static if not used outside of a given compilation unit. Enables the compiler to optimize inlining, reduces the symbol tables, exposes unused functions and in some rare cases exposes mismtaches between function declarations and definitions, but most importantly reduces the number of parfait reports for the extern-function-no-forward-declaration category. This should not result in any functional changes, bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 KB
Line 
1/* $Id: tstDisasm-1.cpp 99775 2023-05-12 12:21:58Z vboxsync $ */
2/** @file
3 * VBox disassembler - Test application
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <VBox/dis.h>
33#include <iprt/test.h>
34#include <iprt/ctype.h>
35#include <iprt/string.h>
36#include <iprt/errcore.h>
37#include <iprt/time.h>
38
39
40DECLASM(int) TestProc32(void);
41DECLASM(int) TestProc32_EndProc(void);
42#ifndef RT_OS_OS2
43DECLASM(int) TestProc64(void);
44DECLASM(int) TestProc64_EndProc(void);
45#endif
46//uint8_t aCode16[] = { 0x66, 0x67, 0x89, 0x07 };
47
48static void testDisas(const char *pszSub, uint8_t const *pabInstrs, uintptr_t uEndPtr, DISCPUMODE enmDisCpuMode)
49{
50 RTTestISub(pszSub);
51 size_t const cbInstrs = uEndPtr - (uintptr_t)pabInstrs;
52 for (size_t off = 0; off < cbInstrs;)
53 {
54 DISSTATE Dis;
55 uint32_t cb = 1;
56#ifndef DIS_CORE_ONLY
57 uint32_t const cErrBefore = RTTestIErrorCount();
58 char szOutput[256] = {0};
59 int rc = DISInstrToStr(&pabInstrs[off], enmDisCpuMode, &Dis, &cb, szOutput, sizeof(szOutput));
60
61 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
62 RTTESTI_CHECK(cb == Dis.cbInstr);
63 RTTESTI_CHECK(cb > 0);
64 RTTESTI_CHECK(cb <= 16);
65 RTStrStripR(szOutput);
66 RTTESTI_CHECK(szOutput[0]);
67 if (szOutput[0])
68 {
69 char *pszBytes = strchr(szOutput, '[');
70 RTTESTI_CHECK(pszBytes);
71 if (pszBytes)
72 {
73 RTTESTI_CHECK(pszBytes[-1] == ' ');
74 RTTESTI_CHECK(RT_C_IS_XDIGIT(pszBytes[1]));
75 RTTESTI_CHECK(pszBytes[cb * 3] == ']');
76 RTTESTI_CHECK(pszBytes[cb * 3 + 1] == ' ');
77
78 size_t cch = strlen(szOutput);
79 RTTESTI_CHECK(szOutput[cch - 1] != ',');
80 }
81 }
82 if (cErrBefore != RTTestIErrorCount())
83 RTTestIFailureDetails("rc=%Rrc, off=%#x (%u) cbInstr=%u enmDisCpuMode=%d\n",
84 rc, off, off, Dis.cbInstr, enmDisCpuMode);
85 RTTestIPrintf(RTTESTLVL_ALWAYS, "%s\n", szOutput);
86
87 /* Check with size-only. */
88 uint32_t cbOnly = 1;
89 DISSTATE DisOnly;
90 rc = DISInstrWithPrefetchedBytes((uintptr_t)&pabInstrs[off], enmDisCpuMode, 0 /*fFilter - none */,
91 Dis.u.abInstr, Dis.cbCachedInstr, NULL, NULL, &DisOnly, &cbOnly);
92
93 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
94 RTTESTI_CHECK(cbOnly == DisOnly.cbInstr);
95 RTTESTI_CHECK_MSG(cbOnly == cb, ("%#x vs %#x\n", cbOnly, cb));
96
97#else /* DIS_CORE_ONLY */
98 int rc = DISInstr(&pabInstrs[off], enmDisCpuMode, &Dis, &cb);
99 RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
100 RTTESTI_CHECK(cb == Dis.cbInstr);
101#endif /* DIS_CORE_ONLY */
102
103 off += cb;
104 }
105}
106
107
108static DECLCALLBACK(int) testReadBytes(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead)
109{
110 RT_NOREF1(cbMinRead);
111 memcpy(&pDis->u.abInstr[offInstr], (void *)((uintptr_t)pDis->uInstrAddr + offInstr), cbMaxRead);
112 pDis->cbCachedInstr = offInstr + cbMaxRead;
113 return VINF_SUCCESS;
114}
115
116
117static void testPerformance(const char *pszSub, uint8_t const *pabInstrs, uintptr_t uEndPtr, DISCPUMODE enmDisCpuMode)
118{
119 RTTestISubF("Performance - %s", pszSub);
120
121 size_t const cbInstrs = uEndPtr - (uintptr_t)pabInstrs;
122 uint64_t cInstrs = 0;
123 uint64_t nsStart = RTTimeNanoTS();
124 for (uint32_t i = 0; i < _512K; i++) /* the samples are way to small. :-) */
125 {
126 for (size_t off = 0; off < cbInstrs; cInstrs++)
127 {
128 uint32_t cb = 1;
129 DISSTATE Dis;
130 DISInstrWithReader((uintptr_t)&pabInstrs[off], enmDisCpuMode, testReadBytes, NULL, &Dis, &cb);
131 off += cb;
132 }
133 }
134 uint64_t cNsElapsed = RTTimeNanoTS() - nsStart;
135
136 RTTestIValueF(cNsElapsed, RTTESTUNIT_NS, "%s-Total", pszSub);
137 RTTestIValueF(cNsElapsed / cInstrs, RTTESTUNIT_NS_PER_CALL, "%s-per-instruction", pszSub);
138}
139
140static void testTwo(void)
141{
142 static const struct
143 {
144 DISCPUMODE enmMode;
145 uint8_t abInstr[24];
146 uint8_t cbParam1;
147 uint8_t cbParam2;
148 uint8_t cbParam3;
149 } s_gInstrs[] =
150 {
151 { DISCPUMODE_64BIT, { 0x48, 0xc7, 0x03, 0x00, 0x00, 0x00, 0x00, }, 8, 8, 0, },
152 };
153 for (unsigned i = 0; i < RT_ELEMENTS(s_gInstrs); i++)
154 {
155 uint32_t cb = 1;
156 DISSTATE Dis;
157 int rc;
158 RTTESTI_CHECK_RC(rc = DISInstr(s_gInstrs[i].abInstr, s_gInstrs[i].enmMode, &Dis, &cb), VINF_SUCCESS);
159 if (rc == VINF_SUCCESS)
160 {
161 uint32_t cb2;
162 RTTESTI_CHECK_MSG((cb2 = DISGetParamSize(&Dis, &Dis.Param1)) == s_gInstrs[i].cbParam1,
163 ("%u: %#x vs %#x\n", i , cb2, s_gInstrs[i].cbParam1));
164#ifndef DIS_CORE_ONLY
165 RTTESTI_CHECK_MSG((cb2 = DISGetParamSize(&Dis, &Dis.Param2)) == s_gInstrs[i].cbParam2,
166 ("%u: %#x vs %#x (%s)\n", i , cb2, s_gInstrs[i].cbParam2, Dis.pCurInstr->pszOpcode));
167#else
168 RTTESTI_CHECK_MSG((cb2 = DISGetParamSize(&Dis, &Dis.Param2)) == s_gInstrs[i].cbParam2,
169 ("%u: %#x vs %#x\n", i , cb2, s_gInstrs[i].cbParam2));
170#endif
171 RTTESTI_CHECK_MSG((cb2 = DISGetParamSize(&Dis, &Dis.Param3)) == s_gInstrs[i].cbParam3,
172 ("%u: %#x vs %#x\n", i , cb2, s_gInstrs[i].cbParam3));
173 }
174 }
175}
176
177
178int main(int argc, char **argv)
179{
180 RT_NOREF2(argc, argv);
181 RTTEST hTest;
182 RTEXITCODE rcExit = RTTestInitAndCreate("tstDisasm", &hTest);
183 if (rcExit)
184 return rcExit;
185 RTTestBanner(hTest);
186
187 static const struct
188 {
189 const char *pszDesc;
190 uint8_t const *pbStart;
191 uintptr_t uEndPtr;
192 DISCPUMODE enmCpuMode;
193 } aSnippets[] =
194 {
195 { "32-bit", (uint8_t const *)(uintptr_t)TestProc32, (uintptr_t)&TestProc32_EndProc, DISCPUMODE_32BIT },
196#ifndef RT_OS_OS2
197 { "64-bit", (uint8_t const *)(uintptr_t)TestProc64, (uintptr_t)&TestProc64_EndProc, DISCPUMODE_64BIT },
198#endif
199 };
200
201 for (unsigned i = 0; i < RT_ELEMENTS(aSnippets); i++)
202 testDisas(aSnippets[i].pszDesc, aSnippets[i].pbStart, aSnippets[i].uEndPtr, aSnippets[i].enmCpuMode);
203
204 testTwo();
205
206 if (RTTestIErrorCount() == 0)
207 {
208 for (unsigned i = 0; i < RT_ELEMENTS(aSnippets); i++)
209 testPerformance(aSnippets[i].pszDesc, aSnippets[i].pbStart, aSnippets[i].uEndPtr, aSnippets[i].enmCpuMode);
210 }
211
212 return RTTestSummaryAndDestroy(hTest);
213}
214
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette