VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstLdr-3.cpp@ 41668

Last change on this file since 41668 was 41668, checked in by vboxsync, 12 years ago

DIS,DIS-users: Drop the operand/parameter formatting during instruction parsing. The desired formatter can do this afterwards if desired. Should save time + size. (DISCPUSTATE is now 256 bytes here on 64-bit linux, was ~406 yesterday.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.1 KB
Line 
1/* $Id: tstLdr-3.cpp 41668 2012-06-12 13:15:51Z vboxsync $ */
2/** @file
3 * IPRT - Testcase for parts of RTLdr*, manual inspection.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <iprt/ldr.h>
32#include <iprt/alloc.h>
33#include <iprt/stream.h>
34#include <iprt/assert.h>
35#include <iprt/initterm.h>
36#include <iprt/err.h>
37#include <iprt/string.h>
38#include <VBox/dis.h>
39
40
41/*******************************************************************************
42* Global Variables *
43*******************************************************************************/
44static RTUINTPTR g_uLoadAddr;
45static RTLDRMOD g_hLdrMod;
46static void *g_pvBits;
47static uint8_t g_cBits;
48
49/**
50 * Current nearest symbol.
51 */
52typedef struct TESTNEARSYM
53{
54 RTUINTPTR Addr;
55 struct TESTSYM
56 {
57 RTUINTPTR Value;
58 unsigned uSymbol;
59 char szName[512];
60 } aSyms[2];
61} TESTNEARSYM, *PTESTNEARSYM;
62
63/**
64 * Enumeration callback function used by RTLdrEnumSymbols().
65 *
66 * @returns iprt status code. Failure will stop the enumeration.
67 * @param hLdrMod The loader module handle.
68 * @param pszSymbol Symbol name. NULL if ordinal only.
69 * @param uSymbol Symbol ordinal, ~0 if not used.
70 * @param Value Symbol value.
71 * @param pvUser The user argument specified to RTLdrEnumSymbols().
72 */
73static DECLCALLBACK(int) testEnumSymbol2(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
74{
75 PTESTNEARSYM pSym = (PTESTNEARSYM)pvUser;
76
77 /* less or equal */
78 if ( Value <= pSym->Addr
79 && ( Value > pSym->aSyms[0].Value
80 || ( Value == pSym->aSyms[0].Value
81 && !pSym->aSyms[0].szName[0]
82 && pszSymbol
83 && *pszSymbol
84 )
85 )
86 )
87 {
88 pSym->aSyms[0].Value = Value;
89 pSym->aSyms[0].uSymbol = uSymbol;
90 pSym->aSyms[0].szName[0] = '\0';
91 if (pszSymbol)
92 strncat(pSym->aSyms[0].szName, pszSymbol, sizeof(pSym->aSyms[0].szName)-1);
93 }
94
95 /* above */
96 if ( Value > pSym->Addr
97 && ( Value < pSym->aSyms[1].Value
98 || ( Value == pSym->aSyms[1].Value
99 && !pSym->aSyms[1].szName[1]
100 && pszSymbol
101 && *pszSymbol
102 )
103 )
104 )
105 {
106 pSym->aSyms[1].Value = Value;
107 pSym->aSyms[1].uSymbol = uSymbol;
108 pSym->aSyms[1].szName[0] = '\0';
109 if (pszSymbol)
110 strncat(pSym->aSyms[1].szName, pszSymbol, sizeof(pSym->aSyms[1].szName)-1);
111 }
112
113 return VINF_SUCCESS;
114}
115
116static int FindNearSymbol(RTUINTPTR uAddr, PTESTNEARSYM pNearSym)
117{
118 RT_ZERO(*pNearSym);
119 pNearSym->Addr = (RTUINTPTR)uAddr;
120 pNearSym->aSyms[1].Value = ~(RTUINTPTR)0;
121 int rc = RTLdrEnumSymbols(g_hLdrMod, RTLDR_ENUM_SYMBOL_FLAGS_ALL, g_pvBits, g_uLoadAddr, testEnumSymbol2, pNearSym);
122 if (RT_FAILURE(rc))
123 RTPrintf("tstLdr-3: Failed to enumerate symbols: %Rra\n", rc);
124 return rc;
125}
126
127static DECLCALLBACK(int) MyGetSymbol(PCDISCPUSTATE pCpu, uint32_t u32Sel, RTUINTPTR uAddress,
128 char *pszBuf, size_t cchBuf, RTINTPTR *poff,
129 void *pvUser)
130{
131 if ( uAddress > RTLdrSize(g_hLdrMod) + g_uLoadAddr
132 || uAddress < g_uLoadAddr)
133 return VERR_SYMBOL_NOT_FOUND;
134
135 TESTNEARSYM NearSym;
136 int rc = FindNearSymbol(uAddress, &NearSym);
137 if (RT_FAILURE(rc))
138 return rc;
139
140 RTStrCopy(pszBuf, cchBuf, NearSym.aSyms[0].szName);
141 *poff = uAddress - NearSym.aSyms[0].Value;
142 return VINF_SUCCESS;
143}
144
145
146/**
147 * @callback_method_impl{FNDISREADBYTES}
148 */
149static DECLCALLBACK(int) MyReadBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
150{
151 memcpy(pbDst, (uint8_t const *)((uintptr_t)uSrcAddr + (uintptr_t)pDisState->apvUserData[0]), cbToRead);
152 return VINF_SUCCESS;
153}
154
155
156static bool MyDisBlock(PDISCPUSTATE pCpu, RTHCUINTPTR pvCodeBlock, int32_t cbMax, RTUINTPTR off,
157 RTUINTPTR uNearAddr, RTUINTPTR uSearchAddr)
158{
159 int32_t i = 0;
160 while (i < cbMax)
161 {
162 bool fQuiet = RTAssertSetQuiet(true);
163 bool fMayPanic = RTAssertSetMayPanic(false);
164 char szOutput[256];
165 unsigned cbInstr;
166 int rc = DISCoreOneWithReader(uNearAddr + i, pCpu->mode,
167 MyReadBytes, (uint8_t *)pvCodeBlock - (uintptr_t)uNearAddr,
168 pCpu, &cbInstr);
169 RTAssertSetMayPanic(fMayPanic);
170 RTAssertSetQuiet(fQuiet);
171 if (RT_FAILURE(rc))
172 return false;
173
174 DISFormatYasmEx(pCpu, szOutput, sizeof(szOutput),
175 DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT | DIS_FMT_FLAGS_BYTES_SPACED,
176 MyGetSymbol, NULL);
177
178 RTPrintf("%s\n", szOutput);
179 if (pvCodeBlock + i + off == uSearchAddr)
180 RTPrintf("^^^^^^^^\n");
181
182 /* next */
183 i += cbInstr;
184 }
185 return true;
186}
187
188
189
190/**
191 * Resolve an external symbol during RTLdrGetBits().
192 *
193 * @returns iprt status code.
194 * @param hLdrMod The loader module handle.
195 * @param pszModule Module name.
196 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
197 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
198 * @param pValue Where to store the symbol value (address).
199 * @param pvUser User argument.
200 */
201static DECLCALLBACK(int) testGetImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
202{
203#if 1
204 RTUINTPTR BaseAddr = *(PCRTUINTPTR)pvUser;
205 *pValue = BaseAddr + UINT32_C(0x604020f0);
206#else
207 *pValue = UINT64_C(0xffffff7f820df000);
208#endif
209 if (g_cBits == 32)
210 *pValue &= UINT32_MAX;
211 return VINF_SUCCESS;
212}
213
214
215/**
216 * Enumeration callback function used by RTLdrEnumSymbols().
217 *
218 * @returns iprt status code. Failure will stop the enumeration.
219 * @param hLdrMod The loader module handle.
220 * @param pszSymbol Symbol name. NULL if ordinal only.
221 * @param uSymbol Symbol ordinal, ~0 if not used.
222 * @param Value Symbol value.
223 * @param pvUser The user argument specified to RTLdrEnumSymbols().
224 */
225static DECLCALLBACK(int) testEnumSymbol1(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
226{
227 RTPrintf(" %RTptr %s (%d)\n", Value, pszSymbol, uSymbol);
228 return VINF_SUCCESS;
229}
230
231
232static int testDisasNear(uint64_t uAddr)
233{
234 TESTNEARSYM NearSym;
235 int rc = FindNearSymbol(uAddr, &NearSym);
236 if (RT_FAILURE(rc))
237 return rc;
238
239 RTPrintf("tstLdr-3: Addr=%RTptr\n"
240 "%RTptr %s (%d) - %RTptr %s (%d)\n",
241 NearSym.Addr,
242 NearSym.aSyms[0].Value, NearSym.aSyms[0].szName, NearSym.aSyms[0].uSymbol,
243 NearSym.aSyms[1].Value, NearSym.aSyms[1].szName, NearSym.aSyms[1].uSymbol);
244 if (NearSym.Addr - NearSym.aSyms[0].Value < 0x10000)
245 {
246 DISCPUSTATE Cpu;
247 memset(&Cpu, 0, sizeof(Cpu));
248#ifdef RT_ARCH_X86 /** @todo select according to the module type. */
249 Cpu.mode = CPUMODE_32BIT;
250#else
251 Cpu.mode = CPUMODE_64BIT;
252#endif
253 uint8_t *pbCode = (uint8_t *)g_pvBits + (NearSym.aSyms[0].Value - g_uLoadAddr);
254 MyDisBlock(&Cpu, (uintptr_t)pbCode,
255 RT_MAX(NearSym.aSyms[1].Value - NearSym.aSyms[0].Value, 0x20000),
256 NearSym.aSyms[0].Value - (RTUINTPTR)pbCode,
257 NearSym.aSyms[0].Value,
258 NearSym.Addr);
259 }
260
261 return VINF_SUCCESS;
262}
263
264int main(int argc, char **argv)
265{
266 RTR3InitExe(argc, &argv, 0);
267
268 int rcRet = 0;
269 if (argc <= 2)
270 {
271 RTPrintf("usage: %s <load-addr> <module> [addr1 []]\n", argv[0]);
272 return 1;
273 }
274
275 /*
276 * Load the module.
277 */
278 g_uLoadAddr = (RTUINTPTR)RTStrToUInt64(argv[1]);
279 int rc = RTLdrOpen(argv[2], 0, RTLDRARCH_WHATEVER, &g_hLdrMod);
280 if (RT_FAILURE(rc))
281 {
282 RTPrintf("tstLdr-3: Failed to open '%s': %Rra\n", argv[2], rc);
283 return 1;
284 }
285 g_cBits = ARCH_BITS;
286
287 g_pvBits = RTMemAlloc(RTLdrSize(g_hLdrMod));
288 rc = RTLdrGetBits(g_hLdrMod, g_pvBits, g_uLoadAddr, testGetImport, &g_uLoadAddr);
289 if (RT_SUCCESS(rc))
290 {
291 if ( argc == 4
292 && argv[3][0] == '*')
293 {
294 /*
295 * Wildcard address mode.
296 */
297 uint64_t uWild = RTStrToUInt64(&argv[3][1]);
298 uint64_t uIncrements = strchr(argv[3], '/') ? RTStrToUInt64(strchr(argv[3], '/') + 1) : 0x1000;
299 if (!uIncrements)
300 uIncrements = 0x1000;
301 uint64_t uMax = RTLdrSize(g_hLdrMod) + g_uLoadAddr;
302 for (uint64_t uCur = g_uLoadAddr + uWild; uCur < uMax; uCur += uIncrements)
303 testDisasNear(uCur);
304 }
305 else if (argc > 3)
306 {
307 /*
308 * User specified addresses within the module.
309 */
310 for (int i = 3; i < argc; i++)
311 {
312 rc = testDisasNear(RTStrToUInt64(argv[i]));
313 if (RT_FAILURE(rc))
314 rcRet++;
315 }
316 }
317 else
318 {
319 /*
320 * Enumerate symbols.
321 */
322 rc = RTLdrEnumSymbols(g_hLdrMod, RTLDR_ENUM_SYMBOL_FLAGS_ALL, g_pvBits, g_uLoadAddr, testEnumSymbol1, NULL);
323 if (RT_FAILURE(rc))
324 {
325 RTPrintf("tstLdr-3: Failed to enumerate symbols: %Rra\n", rc);
326 rcRet++;
327 }
328 }
329 }
330 else
331 {
332 RTPrintf("tstLdr-3: Failed to get bits for '%s' at %RTptr: %Rra\n", argv[2], g_uLoadAddr, rc);
333 rcRet++;
334 }
335 RTMemFree(g_pvBits);
336 RTLdrClose(g_hLdrMod);
337
338 /*
339 * Test result summary.
340 */
341 if (!rcRet)
342 RTPrintf("tstLdr-3: SUCCESS\n");
343 else
344 RTPrintf("tstLdr-3: FAILURE - %d errors\n", rcRet);
345 return !!rcRet;
346}
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