VirtualBox

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

Last change on this file since 32970 was 32878, checked in by vboxsync, 14 years ago

strncat fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.5 KB
Line 
1/* $Id: tstLdr-3.cpp 32878 2010-10-03 20:30:49Z 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
41static bool MyDisBlock(PDISCPUSTATE pCpu, RTHCUINTPTR pvCodeBlock, int32_t cbMax, RTUINTPTR off, RTUINTPTR Addr)
42{
43 int32_t i = 0;
44 while (i < cbMax)
45 {
46 char szOutput[256];
47 uint32_t cbInstr;
48 if (RT_FAILURE(DISInstr(pCpu, pvCodeBlock + i, off, &cbInstr, szOutput)))
49 return false;
50
51 RTPrintf("%s", szOutput);
52 if (pvCodeBlock + i + off == Addr)
53 RTPrintf("^^^^^^^^\n");
54
55 /* next */
56 i += cbInstr;
57 }
58 return true;
59}
60
61
62
63/**
64 * Resolve an external symbol during RTLdrGetBits().
65 *
66 * @returns iprt status code.
67 * @param hLdrMod The loader module handle.
68 * @param pszModule Module name.
69 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
70 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
71 * @param pValue Where to store the symbol value (address).
72 * @param pvUser User argument.
73 */
74static DECLCALLBACK(int) testGetImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
75{
76 RTUINTPTR BaseAddr = *(PCRTUINTPTR)pvUser;
77 *pValue = BaseAddr + UINT32_C(0x604020f0);
78 return VINF_SUCCESS;
79}
80
81
82/**
83 * Enumeration callback function used by RTLdrEnumSymbols().
84 *
85 * @returns iprt status code. Failure will stop the enumeration.
86 * @param hLdrMod The loader module handle.
87 * @param pszSymbol Symbol name. NULL if ordinal only.
88 * @param uSymbol Symbol ordinal, ~0 if not used.
89 * @param Value Symbol value.
90 * @param pvUser The user argument specified to RTLdrEnumSymbols().
91 */
92static DECLCALLBACK(int) testEnumSymbol1(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
93{
94 RTPrintf(" %RTptr %s (%d)\n", Value, pszSymbol, uSymbol);
95 return VINF_SUCCESS;
96}
97
98/**
99 * Current nearest symbol.
100 */
101typedef struct TESTNEARSYM
102{
103 RTUINTPTR Addr;
104 struct TESTSYM
105 {
106 RTUINTPTR Value;
107 unsigned uSymbol;
108 char szName[512];
109 } aSyms[2];
110} TESTNEARSYM, *PTESTNEARSYM;
111
112/**
113 * Enumeration callback function used by RTLdrEnumSymbols().
114 *
115 * @returns iprt status code. Failure will stop the enumeration.
116 * @param hLdrMod The loader module handle.
117 * @param pszSymbol Symbol name. NULL if ordinal only.
118 * @param uSymbol Symbol ordinal, ~0 if not used.
119 * @param Value Symbol value.
120 * @param pvUser The user argument specified to RTLdrEnumSymbols().
121 */
122static DECLCALLBACK(int) testEnumSymbol2(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
123{
124 PTESTNEARSYM pSym = (PTESTNEARSYM)pvUser;
125
126 /* less or equal */
127 if ( Value <= pSym->Addr
128 && ( Value > pSym->aSyms[0].Value
129 || ( Value == pSym->aSyms[0].Value
130 && !pSym->aSyms[0].szName[0]
131 && pszSymbol
132 && *pszSymbol
133 )
134 )
135 )
136 {
137 pSym->aSyms[0].Value = Value;
138 pSym->aSyms[0].uSymbol = uSymbol;
139 pSym->aSyms[0].szName[0] = '\0';
140 if (pszSymbol)
141 strncat(pSym->aSyms[0].szName, pszSymbol, sizeof(pSym->aSyms[0].szName)-1);
142 }
143
144 /* above */
145 if ( Value > pSym->Addr
146 && ( Value < pSym->aSyms[1].Value
147 || ( Value == pSym->aSyms[1].Value
148 && !pSym->aSyms[1].szName[1]
149 && pszSymbol
150 && *pszSymbol
151 )
152 )
153 )
154 {
155 pSym->aSyms[1].Value = Value;
156 pSym->aSyms[1].uSymbol = uSymbol;
157 pSym->aSyms[1].szName[0] = '\0';
158 if (pszSymbol)
159 strncat(pSym->aSyms[1].szName, pszSymbol, sizeof(pSym->aSyms[1].szName)-1);
160 }
161
162 return VINF_SUCCESS;
163}
164
165
166int main(int argc, char **argv)
167{
168 RTR3Init();
169
170 int rcRet = 0;
171 if (argc <= 2)
172 {
173 RTPrintf("usage: %s <load-addr> <module> [addr1 []]\n", argv[0]);
174 return 1;
175 }
176
177 /*
178 * Load the module.
179 */
180 RTUINTPTR LoadAddr = (RTUINTPTR)RTStrToUInt64(argv[1]);
181 RTLDRMOD hLdrMod;
182 int rc = RTLdrOpen(argv[2], 0, RTLDRARCH_WHATEVER, &hLdrMod);
183 if (RT_FAILURE(rc))
184 {
185 RTPrintf("tstLdr-3: Failed to open '%s': %Rra\n", argv[2], rc);
186 return 1;
187 }
188
189 void *pvBits = RTMemAlloc(RTLdrSize(hLdrMod));
190 rc = RTLdrGetBits(hLdrMod, pvBits, LoadAddr, testGetImport, &LoadAddr);
191 if (RT_SUCCESS(rc))
192 {
193 if (argc > 3)
194 {
195 for (int i = 3; i < argc; i++)
196 {
197 TESTNEARSYM NearSym;
198 RT_ZERO(NearSym);
199 NearSym.Addr = (RTUINTPTR)RTStrToUInt64(argv[i]);
200 NearSym.aSyms[1].Value = ~(RTUINTPTR)0;
201 rc = RTLdrEnumSymbols(hLdrMod, RTLDR_ENUM_SYMBOL_FLAGS_ALL, pvBits, LoadAddr, testEnumSymbol2, &NearSym);
202 if (RT_SUCCESS(rc))
203 {
204 RTPrintf("tstLdr-3: Addr=%RTptr\n"
205 "%RTptr %s (%d) - %RTptr %s (%d)\n",
206 NearSym.Addr,
207 NearSym.aSyms[0].Value, NearSym.aSyms[0].szName, NearSym.aSyms[0].uSymbol,
208 NearSym.aSyms[1].Value, NearSym.aSyms[1].szName, NearSym.aSyms[1].uSymbol);
209 if (NearSym.Addr - NearSym.aSyms[0].Value < 0x10000)
210 {
211 DISCPUSTATE Cpu;
212 memset(&Cpu, 0, sizeof(Cpu));
213#ifdef RT_ARCH_X86 /** @todo select according to the module type. */
214 Cpu.mode = CPUMODE_32BIT;
215#else
216 Cpu.mode = CPUMODE_64BIT;
217#endif
218 uint8_t *pbCode = (uint8_t *)pvBits + (NearSym.aSyms[0].Value - LoadAddr);
219 MyDisBlock(&Cpu, (uintptr_t)pbCode,
220 RT_MAX(NearSym.aSyms[1].Value - NearSym.aSyms[0].Value, 0x20000),
221 NearSym.aSyms[0].Value - (RTUINTPTR)pbCode,
222 NearSym.Addr);
223 }
224 }
225 else
226 {
227 RTPrintf("tstLdr-3: Failed to enumerate symbols: %Rra\n", rc);
228 rcRet++;
229 }
230 }
231 }
232 else
233 {
234 /*
235 * Enumerate symbols.
236 */
237 rc = RTLdrEnumSymbols(hLdrMod, RTLDR_ENUM_SYMBOL_FLAGS_ALL, pvBits, LoadAddr, testEnumSymbol1, NULL);
238 if (RT_FAILURE(rc))
239 {
240 RTPrintf("tstLdr-3: Failed to enumerate symbols: %Rra\n", rc);
241 rcRet++;
242 }
243 }
244 }
245 else
246 {
247 RTPrintf("tstLdr-3: Failed to get bits for '%s' at %RTptr: %Rra\n", argv[2], LoadAddr, rc);
248 rcRet++;
249 }
250 RTMemFree(pvBits);
251 RTLdrClose(hLdrMod);
252
253 /*
254 * Test result summary.
255 */
256 if (!rcRet)
257 RTPrintf("tstLdr-3: SUCCESS\n");
258 else
259 RTPrintf("tstLdr-3: FAILURE - %d errors\n", rcRet);
260 return !!rcRet;
261}
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