VirtualBox

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

Last change on this file since 41605 was 41078, checked in by vboxsync, 13 years ago

tstLdr-3: out of range fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.0 KB
Line 
1/* $Id: tstLdr-3.cpp 41078 2012-04-27 08:44:35Z 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
146static DECLCALLBACK(int) MyReadBytes(RTUINTPTR uSrc, uint8_t *pbDst, unsigned cb, void *pvUser)
147{
148 PDISCPUSTATE pCpu = (PDISCPUSTATE)pvUser;
149 memcpy(pbDst, (uint8_t const *)((uintptr_t)uSrc + (uintptr_t)pCpu->apvUserData[0]), cb);
150 return VINF_SUCCESS;
151}
152
153
154static bool MyDisBlock(PDISCPUSTATE pCpu, RTHCUINTPTR pvCodeBlock, int32_t cbMax, RTUINTPTR off,
155 RTUINTPTR uNearAddr, RTUINTPTR uSearchAddr)
156{
157 int32_t i = 0;
158 while (i < cbMax)
159 {
160 bool fQuiet = RTAssertSetQuiet(true);
161 bool fMayPanic = RTAssertSetMayPanic(false);
162 char szOutput[256];
163 unsigned cbInstr;
164 int rc = DISCoreOneEx(uNearAddr + i, pCpu->mode,
165 MyReadBytes, (uint8_t *)pvCodeBlock - (uintptr_t)uNearAddr,
166 pCpu, &cbInstr);
167 RTAssertSetMayPanic(fMayPanic);
168 RTAssertSetQuiet(fQuiet);
169 if (RT_FAILURE(rc))
170 return false;
171
172 DISFormatYasmEx(pCpu, szOutput, sizeof(szOutput),
173 DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT | DIS_FMT_FLAGS_BYTES_SPACED,
174 MyGetSymbol, NULL);
175
176 RTPrintf("%s\n", szOutput);
177 if (pvCodeBlock + i + off == uSearchAddr)
178 RTPrintf("^^^^^^^^\n");
179
180 /* next */
181 i += cbInstr;
182 }
183 return true;
184}
185
186
187
188/**
189 * Resolve an external symbol during RTLdrGetBits().
190 *
191 * @returns iprt status code.
192 * @param hLdrMod The loader module handle.
193 * @param pszModule Module name.
194 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
195 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
196 * @param pValue Where to store the symbol value (address).
197 * @param pvUser User argument.
198 */
199static DECLCALLBACK(int) testGetImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
200{
201#if 1
202 RTUINTPTR BaseAddr = *(PCRTUINTPTR)pvUser;
203 *pValue = BaseAddr + UINT32_C(0x604020f0);
204#else
205 *pValue = UINT64_C(0xffffff7f820df000);
206#endif
207 if (g_cBits == 32)
208 *pValue &= UINT32_MAX;
209 return VINF_SUCCESS;
210}
211
212
213/**
214 * Enumeration callback function used by RTLdrEnumSymbols().
215 *
216 * @returns iprt status code. Failure will stop the enumeration.
217 * @param hLdrMod The loader module handle.
218 * @param pszSymbol Symbol name. NULL if ordinal only.
219 * @param uSymbol Symbol ordinal, ~0 if not used.
220 * @param Value Symbol value.
221 * @param pvUser The user argument specified to RTLdrEnumSymbols().
222 */
223static DECLCALLBACK(int) testEnumSymbol1(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
224{
225 RTPrintf(" %RTptr %s (%d)\n", Value, pszSymbol, uSymbol);
226 return VINF_SUCCESS;
227}
228
229
230static int testDisasNear(uint64_t uAddr)
231{
232 TESTNEARSYM NearSym;
233 int rc = FindNearSymbol(uAddr, &NearSym);
234 if (RT_FAILURE(rc))
235 return rc;
236
237 RTPrintf("tstLdr-3: Addr=%RTptr\n"
238 "%RTptr %s (%d) - %RTptr %s (%d)\n",
239 NearSym.Addr,
240 NearSym.aSyms[0].Value, NearSym.aSyms[0].szName, NearSym.aSyms[0].uSymbol,
241 NearSym.aSyms[1].Value, NearSym.aSyms[1].szName, NearSym.aSyms[1].uSymbol);
242 if (NearSym.Addr - NearSym.aSyms[0].Value < 0x10000)
243 {
244 DISCPUSTATE Cpu;
245 memset(&Cpu, 0, sizeof(Cpu));
246#ifdef RT_ARCH_X86 /** @todo select according to the module type. */
247 Cpu.mode = CPUMODE_32BIT;
248#else
249 Cpu.mode = CPUMODE_64BIT;
250#endif
251 uint8_t *pbCode = (uint8_t *)g_pvBits + (NearSym.aSyms[0].Value - g_uLoadAddr);
252 MyDisBlock(&Cpu, (uintptr_t)pbCode,
253 RT_MAX(NearSym.aSyms[1].Value - NearSym.aSyms[0].Value, 0x20000),
254 NearSym.aSyms[0].Value - (RTUINTPTR)pbCode,
255 NearSym.aSyms[0].Value,
256 NearSym.Addr);
257 }
258
259 return VINF_SUCCESS;
260}
261
262int main(int argc, char **argv)
263{
264 RTR3InitExe(argc, &argv, 0);
265
266 int rcRet = 0;
267 if (argc <= 2)
268 {
269 RTPrintf("usage: %s <load-addr> <module> [addr1 []]\n", argv[0]);
270 return 1;
271 }
272
273 /*
274 * Load the module.
275 */
276 g_uLoadAddr = (RTUINTPTR)RTStrToUInt64(argv[1]);
277 int rc = RTLdrOpen(argv[2], 0, RTLDRARCH_WHATEVER, &g_hLdrMod);
278 if (RT_FAILURE(rc))
279 {
280 RTPrintf("tstLdr-3: Failed to open '%s': %Rra\n", argv[2], rc);
281 return 1;
282 }
283 g_cBits = ARCH_BITS;
284
285 g_pvBits = RTMemAlloc(RTLdrSize(g_hLdrMod));
286 rc = RTLdrGetBits(g_hLdrMod, g_pvBits, g_uLoadAddr, testGetImport, &g_uLoadAddr);
287 if (RT_SUCCESS(rc))
288 {
289 if ( argc == 4
290 && argv[3][0] == '*')
291 {
292 /*
293 * Wildcard address mode.
294 */
295 uint64_t uWild = RTStrToUInt64(&argv[3][1]);
296 uint64_t uIncrements = strchr(argv[3], '/') ? RTStrToUInt64(strchr(argv[3], '/') + 1) : 0x1000;
297 if (!uIncrements)
298 uIncrements = 0x1000;
299 uint64_t uMax = RTLdrSize(g_hLdrMod) + g_uLoadAddr;
300 for (uint64_t uCur = g_uLoadAddr + uWild; uCur < uMax; uCur += uIncrements)
301 testDisasNear(uCur);
302 }
303 else if (argc > 3)
304 {
305 /*
306 * User specified addresses within the module.
307 */
308 for (int i = 3; i < argc; i++)
309 {
310 rc = testDisasNear(RTStrToUInt64(argv[i]));
311 if (RT_FAILURE(rc))
312 rcRet++;
313 }
314 }
315 else
316 {
317 /*
318 * Enumerate symbols.
319 */
320 rc = RTLdrEnumSymbols(g_hLdrMod, RTLDR_ENUM_SYMBOL_FLAGS_ALL, g_pvBits, g_uLoadAddr, testEnumSymbol1, NULL);
321 if (RT_FAILURE(rc))
322 {
323 RTPrintf("tstLdr-3: Failed to enumerate symbols: %Rra\n", rc);
324 rcRet++;
325 }
326 }
327 }
328 else
329 {
330 RTPrintf("tstLdr-3: Failed to get bits for '%s' at %RTptr: %Rra\n", argv[2], g_uLoadAddr, rc);
331 rcRet++;
332 }
333 RTMemFree(g_pvBits);
334 RTLdrClose(g_hLdrMod);
335
336 /*
337 * Test result summary.
338 */
339 if (!rcRet)
340 RTPrintf("tstLdr-3: SUCCESS\n");
341 else
342 RTPrintf("tstLdr-3: FAILURE - %d errors\n", rcRet);
343 return !!rcRet;
344}
Note: See TracBrowser for help on using the repository browser.

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