VirtualBox

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

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

tstLdr-3: Extended the tool.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.9 KB
Line 
1/* $Id: tstLdr-3.cpp 41059 2012-04-26 00:52:15Z 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;
47
48/**
49 * Current nearest symbol.
50 */
51typedef struct TESTNEARSYM
52{
53 RTUINTPTR Addr;
54 struct TESTSYM
55 {
56 RTUINTPTR Value;
57 unsigned uSymbol;
58 char szName[512];
59 } aSyms[2];
60} TESTNEARSYM, *PTESTNEARSYM;
61
62/**
63 * Enumeration callback function used by RTLdrEnumSymbols().
64 *
65 * @returns iprt status code. Failure will stop the enumeration.
66 * @param hLdrMod The loader module handle.
67 * @param pszSymbol Symbol name. NULL if ordinal only.
68 * @param uSymbol Symbol ordinal, ~0 if not used.
69 * @param Value Symbol value.
70 * @param pvUser The user argument specified to RTLdrEnumSymbols().
71 */
72static DECLCALLBACK(int) testEnumSymbol2(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
73{
74 PTESTNEARSYM pSym = (PTESTNEARSYM)pvUser;
75
76 /* less or equal */
77 if ( Value <= pSym->Addr
78 && ( Value > pSym->aSyms[0].Value
79 || ( Value == pSym->aSyms[0].Value
80 && !pSym->aSyms[0].szName[0]
81 && pszSymbol
82 && *pszSymbol
83 )
84 )
85 )
86 {
87 pSym->aSyms[0].Value = Value;
88 pSym->aSyms[0].uSymbol = uSymbol;
89 pSym->aSyms[0].szName[0] = '\0';
90 if (pszSymbol)
91 strncat(pSym->aSyms[0].szName, pszSymbol, sizeof(pSym->aSyms[0].szName)-1);
92 }
93
94 /* above */
95 if ( Value > pSym->Addr
96 && ( Value < pSym->aSyms[1].Value
97 || ( Value == pSym->aSyms[1].Value
98 && !pSym->aSyms[1].szName[1]
99 && pszSymbol
100 && *pszSymbol
101 )
102 )
103 )
104 {
105 pSym->aSyms[1].Value = Value;
106 pSym->aSyms[1].uSymbol = uSymbol;
107 pSym->aSyms[1].szName[0] = '\0';
108 if (pszSymbol)
109 strncat(pSym->aSyms[1].szName, pszSymbol, sizeof(pSym->aSyms[1].szName)-1);
110 }
111
112 return VINF_SUCCESS;
113}
114
115static int FindNearSymbol(RTUINTPTR uAddr, PTESTNEARSYM pNearSym)
116{
117 RT_ZERO(*pNearSym);
118 pNearSym->Addr = (RTUINTPTR)uAddr;
119 pNearSym->aSyms[1].Value = ~(RTUINTPTR)0;
120 int rc = RTLdrEnumSymbols(g_hLdrMod, RTLDR_ENUM_SYMBOL_FLAGS_ALL, g_pvBits, g_uLoadAddr, testEnumSymbol2, pNearSym);
121 if (RT_FAILURE(rc))
122 RTPrintf("tstLdr-3: Failed to enumerate symbols: %Rra\n", rc);
123 return rc;
124}
125
126static DECLCALLBACK(int) MyGetSymbol(PCDISCPUSTATE pCpu, uint32_t u32Sel, RTUINTPTR uAddress,
127 char *pszBuf, size_t cchBuf, RTINTPTR *poff,
128 void *pvUser)
129{
130 if ( uAddress > RTLdrSize(g_hLdrMod) + g_uLoadAddr
131 || uAddress < g_uLoadAddr)
132 return VERR_SYMBOL_NOT_FOUND;
133
134 TESTNEARSYM NearSym;
135 int rc = FindNearSymbol(uAddress, &NearSym);
136 if (RT_FAILURE(rc))
137 return rc;
138
139 RTStrCopy(pszBuf, cchBuf, NearSym.aSyms[0].szName);
140 *poff = uAddress - NearSym.aSyms[0].Value;
141 return VINF_SUCCESS;
142}
143
144
145static DECLCALLBACK(int) MyReadBytes(RTUINTPTR uSrc, uint8_t *pbDst, unsigned cb, void *pvUser)
146{
147 PDISCPUSTATE pCpu = (PDISCPUSTATE)pvUser;
148 memcpy(pbDst, (uint8_t const *)((uintptr_t)uSrc + (uintptr_t)pCpu->apvUserData[0]), cb);
149 return VINF_SUCCESS;
150}
151
152
153static bool MyDisBlock(PDISCPUSTATE pCpu, RTHCUINTPTR pvCodeBlock, int32_t cbMax, RTUINTPTR off,
154 RTUINTPTR uNearAddr, RTUINTPTR uSearchAddr)
155{
156 int32_t i = 0;
157 while (i < cbMax)
158 {
159 bool fQuiet = RTAssertSetQuiet(true);
160 bool fMayPanic = RTAssertSetMayPanic(false);
161 char szOutput[256];
162 unsigned cbInstr;
163 int rc = DISCoreOneEx(uNearAddr + i, pCpu->mode,
164 MyReadBytes, (uint8_t *)pvCodeBlock - (uintptr_t)uNearAddr,
165 pCpu, &cbInstr);
166 RTAssertSetMayPanic(fMayPanic);
167 RTAssertSetQuiet(fQuiet);
168 if (RT_FAILURE(rc))
169 return false;
170
171 DISFormatYasmEx(pCpu, szOutput, sizeof(szOutput),
172 DIS_FMT_FLAGS_RELATIVE_BRANCH | DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT | DIS_FMT_FLAGS_BYTES_SPACED,
173 MyGetSymbol, NULL);
174
175 RTPrintf("%s\n", szOutput);
176 if (pvCodeBlock + i + off == uSearchAddr)
177 RTPrintf("^^^^^^^^\n");
178
179 /* next */
180 i += cbInstr;
181 }
182 return true;
183}
184
185
186
187/**
188 * Resolve an external symbol during RTLdrGetBits().
189 *
190 * @returns iprt status code.
191 * @param hLdrMod The loader module handle.
192 * @param pszModule Module name.
193 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
194 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
195 * @param pValue Where to store the symbol value (address).
196 * @param pvUser User argument.
197 */
198static DECLCALLBACK(int) testGetImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
199{
200#if 1
201 RTUINTPTR BaseAddr = *(PCRTUINTPTR)pvUser;
202 *pValue = BaseAddr + UINT32_C(0x604020f0);
203#else
204 *pValue = UINT64_C(0xffffff7f820df000);
205#endif
206 return VINF_SUCCESS;
207}
208
209
210/**
211 * Enumeration callback function used by RTLdrEnumSymbols().
212 *
213 * @returns iprt status code. Failure will stop the enumeration.
214 * @param hLdrMod The loader module handle.
215 * @param pszSymbol Symbol name. NULL if ordinal only.
216 * @param uSymbol Symbol ordinal, ~0 if not used.
217 * @param Value Symbol value.
218 * @param pvUser The user argument specified to RTLdrEnumSymbols().
219 */
220static DECLCALLBACK(int) testEnumSymbol1(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
221{
222 RTPrintf(" %RTptr %s (%d)\n", Value, pszSymbol, uSymbol);
223 return VINF_SUCCESS;
224}
225
226
227static int testDisasNear(uint64_t uAddr)
228{
229 TESTNEARSYM NearSym;
230 int rc = FindNearSymbol(uAddr, &NearSym);
231 if (RT_FAILURE(rc))
232 return rc;
233
234 RTPrintf("tstLdr-3: Addr=%RTptr\n"
235 "%RTptr %s (%d) - %RTptr %s (%d)\n",
236 NearSym.Addr,
237 NearSym.aSyms[0].Value, NearSym.aSyms[0].szName, NearSym.aSyms[0].uSymbol,
238 NearSym.aSyms[1].Value, NearSym.aSyms[1].szName, NearSym.aSyms[1].uSymbol);
239 if (NearSym.Addr - NearSym.aSyms[0].Value < 0x10000)
240 {
241 DISCPUSTATE Cpu;
242 memset(&Cpu, 0, sizeof(Cpu));
243#ifdef RT_ARCH_X86 /** @todo select according to the module type. */
244 Cpu.mode = CPUMODE_32BIT;
245#else
246 Cpu.mode = CPUMODE_64BIT;
247#endif
248 uint8_t *pbCode = (uint8_t *)g_pvBits + (NearSym.aSyms[0].Value - g_uLoadAddr);
249 MyDisBlock(&Cpu, (uintptr_t)pbCode,
250 RT_MAX(NearSym.aSyms[1].Value - NearSym.aSyms[0].Value, 0x20000),
251 NearSym.aSyms[0].Value - (RTUINTPTR)pbCode,
252 NearSym.aSyms[0].Value,
253 NearSym.Addr);
254 }
255
256 return VINF_SUCCESS;
257}
258
259int main(int argc, char **argv)
260{
261 RTR3InitExe(argc, &argv, 0);
262
263 int rcRet = 0;
264 if (argc <= 2)
265 {
266 RTPrintf("usage: %s <load-addr> <module> [addr1 []]\n", argv[0]);
267 return 1;
268 }
269
270 /*
271 * Load the module.
272 */
273 g_uLoadAddr = (RTUINTPTR)RTStrToUInt64(argv[1]);
274 int rc = RTLdrOpen(argv[2], 0, RTLDRARCH_WHATEVER, &g_hLdrMod);
275 if (RT_FAILURE(rc))
276 {
277 RTPrintf("tstLdr-3: Failed to open '%s': %Rra\n", argv[2], rc);
278 return 1;
279 }
280
281 g_pvBits = RTMemAlloc(RTLdrSize(g_hLdrMod));
282 rc = RTLdrGetBits(g_hLdrMod, g_pvBits, g_uLoadAddr, testGetImport, &g_uLoadAddr);
283 if (RT_SUCCESS(rc))
284 {
285 if ( argc == 4
286 && argv[3][0] == '*')
287 {
288 /*
289 * Wildcard address mode.
290 */
291 uint64_t uWild = RTStrToUInt64(&argv[3][1]);
292 uint64_t uIncrements = strchr(argv[3], '/') ? RTStrToUInt64(strchr(argv[3], '/') + 1) : 0x1000;
293 if (!uIncrements)
294 uIncrements = 0x1000;
295 uint64_t uMax = RTLdrSize(g_hLdrMod) + g_uLoadAddr;
296 for (uint64_t uCur = g_uLoadAddr + uWild; uCur < uMax; uCur += uIncrements)
297 testDisasNear(uCur);
298 }
299 else if (argc > 3)
300 {
301 /*
302 * User specified addresses within the module.
303 */
304 for (int i = 3; i < argc; i++)
305 {
306 rc = testDisasNear(RTStrToUInt64(argv[i]));
307 if (RT_FAILURE(rc))
308 rcRet++;
309 }
310 }
311 else
312 {
313 /*
314 * Enumerate symbols.
315 */
316 rc = RTLdrEnumSymbols(g_hLdrMod, RTLDR_ENUM_SYMBOL_FLAGS_ALL, g_pvBits, g_uLoadAddr, testEnumSymbol1, NULL);
317 if (RT_FAILURE(rc))
318 {
319 RTPrintf("tstLdr-3: Failed to enumerate symbols: %Rra\n", rc);
320 rcRet++;
321 }
322 }
323 }
324 else
325 {
326 RTPrintf("tstLdr-3: Failed to get bits for '%s' at %RTptr: %Rra\n", argv[2], g_uLoadAddr, rc);
327 rcRet++;
328 }
329 RTMemFree(g_pvBits);
330 RTLdrClose(g_hLdrMod);
331
332 /*
333 * Test result summary.
334 */
335 if (!rcRet)
336 RTPrintf("tstLdr-3: SUCCESS\n");
337 else
338 RTPrintf("tstLdr-3: FAILURE - %d errors\n", rcRet);
339 return !!rcRet;
340}
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