VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstLdr.cpp@ 4337

Last change on this file since 4337 was 4071, checked in by vboxsync, 17 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.1 KB
Line 
1/* $Id: tstLdr.cpp 4071 2007-08-07 17:07:59Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Testcase for parts of RTLdr*.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <iprt/ldr.h>
23#include <iprt/alloc.h>
24#include <iprt/stream.h>
25#include <iprt/assert.h>
26#include <iprt/runtime.h>
27#include <iprt/err.h>
28#include <iprt/string.h>
29
30
31/*******************************************************************************
32* Global Variables *
33*******************************************************************************/
34/** If set, don't bitch when failing to resolve symbols. */
35static bool g_fDontBitchOnResolveFailure = false;
36
37/**
38 * Resolve an external symbol during RTLdrGetBits().
39 *
40 * @returns iprt status code.
41 * @param hLdrMod The loader module handle.
42 * @param pszModule Module name.
43 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
44 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
45 * @param pValue Where to store the symbol value (address).
46 * @param pvUser User argument.
47 */
48static DECLCALLBACK(int) testGetImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
49{
50 /* check the name format and only permit certain names */
51 *pValue = 0xabcdef0f;
52 return VINF_SUCCESS;
53}
54
55
56/**
57 * One test iteration with one file.
58 *
59 * The test is very simple, we load the the file three times
60 * into two different regions. The first two into each of the
61 * regions the for compare usage. The third is loaded into one
62 * and then relocated between the two and other locations a few times.
63 *
64 * @returns number of errors.
65 * @param pszFilename The file to load the mess with.
66 */
67static int testLdrOne(const char *pszFilename)
68{
69 int rcRet = 0;
70 size_t cbImage = 0;
71 struct Load
72 {
73 RTLDRMOD hLdrMod;
74 void *pvBits;
75 RTUINTPTR Addr;
76 const char *pszName;
77 } aLoads[6] =
78 {
79 { NULL, NULL, 0xefefef00, "foo" },
80 { NULL, NULL, 0x40404040, "bar" },
81 { NULL, NULL, 0xefefef00, "foobar" },
82 { NULL, NULL, 0xefefef00, "kLdr-foo" },
83 { NULL, NULL, 0x40404040, "kLdr-bar" },
84 { NULL, NULL, 0xefefef00, "kLdr-foobar" }
85 };
86 unsigned i;
87
88 /*
89 * Load them.
90 */
91 for (i = 0; i < ELEMENTS(aLoads); i++)
92 {
93 int rc;
94 if (!strncmp(aLoads[i].pszName, "kLdr-", sizeof("kLdr-") - 1))
95 rc = RTLdrOpenkLdr(pszFilename, &aLoads[i].hLdrMod);
96 else
97 rc = RTLdrOpen(pszFilename, &aLoads[i].hLdrMod);
98 if (RT_FAILURE(rc))
99 {
100 RTPrintf("tstLdr: Failed to open '%s'/%d, rc=%Rrc. aborting test.\n", pszFilename, i, rc);
101 Assert(aLoads[i].hLdrMod == NIL_RTLDRMOD);
102 rcRet++;
103 break;
104 }
105
106 /* size it */
107 size_t cb = RTLdrSize(aLoads[i].hLdrMod);
108 if (cbImage && cb != cbImage)
109 {
110 RTPrintf("tstLdr: Size mismatch '%s'/%d. aborting test.\n", pszFilename, i);
111 rcRet++;
112 break;
113 }
114 cbImage = cb;
115
116 /* Allocate bits. */
117 aLoads[i].pvBits = RTMemAlloc(cb);
118 if (!aLoads[i].pvBits)
119 {
120 RTPrintf("tstLdr: Out of memory '%s'/%d cbImage=%d. aborting test.\n", pszFilename, i, cbImage);
121 rcRet++;
122 break;
123 }
124
125 /* Get the bits. */
126 rc = RTLdrGetBits(aLoads[i].hLdrMod, aLoads[i].pvBits, aLoads[i].Addr, testGetImport, NULL);
127 if (RT_FAILURE(rc))
128 {
129 RTPrintf("tstLdr: Failed to get bits for '%s'/%d, rc=%Rrc. aborting test\n", pszFilename, i, rc);
130 rcRet++;
131 break;
132 }
133 }
134
135 /*
136 * Continue with the relocations and symbol resolving.
137 */
138 if (!rcRet)
139 {
140 static RTUINTPTR aRels[] =
141 {
142 0xefefef00, /* same. */
143 0x40404040, /* the other. */
144 0xefefef00, /* back. */
145 0x40404040, /* the other. */
146 0xefefef00, /* back again. */
147 0x77773420, /* somewhere entirely else. */
148 0xf0000000, /* somewhere entirely else. */
149 0x40404040, /* the other. */
150 0xefefef00 /* back again. */
151 };
152 struct Symbols
153 {
154 /** The symbol offset. -1 indicates the first time. */
155 unsigned off;
156 /** The symbol name. */
157 const char *pszName;
158 } aSyms[] =
159 {
160 { ~0, "Entrypoint" },
161 { ~0, "SomeExportFunction1" },
162 { ~0, "SomeExportFunction2" },
163 { ~0, "SomeExportFunction3" },
164 { ~0, "SomeExportFunction4" },
165 { ~0, "SomeExportFunction5" },
166 { ~0, "SomeExportFunction5" },
167 { ~0, "DISCoreOne" }
168 };
169
170 unsigned iRel = 0;
171 for (;;)
172 {
173 /* Compare all which are at the same address. */
174 for (i = 0; i < ELEMENTS(aLoads) - 1; i++)
175 {
176 for (unsigned j = i + 1; j < ELEMENTS(aLoads); j++)
177 {
178 if (aLoads[j].Addr == aLoads[i].Addr)
179 {
180 if (memcmp(aLoads[j].pvBits, aLoads[i].pvBits, cbImage))
181 {
182 RTPrintf("tstLdr: Mismatch between load %d and %d. ('%s')\n", j, i, pszFilename);
183 const uint8_t *pu8J = (const uint8_t *)aLoads[j].pvBits;
184 const uint8_t *pu8I = (const uint8_t *)aLoads[i].pvBits;
185 for (uint32_t off = 0; off < cbImage; off++, pu8J++, pu8I++)
186 if (*pu8J != *pu8I)
187 RTPrintf(" %08x %02x != %02x\n", off, *pu8J, *pu8I);
188 rcRet++;
189 }
190 }
191 }
192 }
193
194 /* compare symbols. */
195 for (i = 0; i < ELEMENTS(aLoads); i++)
196 {
197 for (unsigned iSym = 0; iSym < ELEMENTS(aSyms); iSym++)
198 {
199 RTUINTPTR Value;
200 int rc = RTLdrGetSymbolEx(aLoads[i].hLdrMod, aLoads[i].pvBits, aLoads[i].Addr, aSyms[iSym].pszName, &Value);
201 if (RT_SUCCESS(rc))
202 {
203 unsigned off = Value - aLoads[i].Addr;
204 if (off < cbImage)
205 {
206 if (aSyms[iSym].off == ~0U)
207 aSyms[iSym].off = off;
208 else if (off != aSyms[iSym].off)
209 {
210 RTPrintf("tstLdr: Mismatching symbol '%s' in '%s'/%d. expected off=%d got %d\n",
211 aSyms[iSym].pszName, pszFilename, i, aSyms[iSym].off, off);
212 rcRet++;
213 }
214 }
215 else
216 {
217 RTPrintf("tstLdr: Invalid value for symbol '%s' in '%s'/%d. off=%#x Value=%#x\n",
218 aSyms[iSym].pszName, pszFilename, i, off, Value);
219 rcRet++;
220 }
221 }
222 else if (!g_fDontBitchOnResolveFailure)
223 {
224 RTPrintf("tstLdr: Failed to resolve symbol '%s' in '%s'/%d.\n", aSyms[iSym].pszName, pszFilename, i);
225 rcRet++;
226 }
227 }
228 }
229
230 if (iRel >= ELEMENTS(aRels))
231 break;
232
233 /* relocate it stuff. */
234 int rc = RTLdrRelocate(aLoads[2].hLdrMod, aLoads[2].pvBits, aRels[iRel], aLoads[2].Addr, testGetImport, NULL);
235 if (RT_FAILURE(rc))
236 {
237 RTPrintf("tstLdr: Relocate of '%s' from %#x to %#x failed, rc=%Rrc. Aborting test.\n",
238 pszFilename, aRels[iRel], aLoads[2].Addr, rc);
239 rcRet++;
240 break;
241 }
242 aLoads[2].Addr = aRels[iRel];
243
244 /* next */
245 iRel++;
246 }
247 }
248
249 /*
250 * Clean up.
251 */
252 for (i = 0; i < ELEMENTS(aLoads); i++)
253 {
254 if (aLoads[i].pvBits)
255 RTMemFree(aLoads[i].pvBits);
256 if (aLoads[i].hLdrMod)
257 {
258 int rc = RTLdrClose(aLoads[i].hLdrMod);
259 if (RT_FAILURE(rc))
260 {
261 RTPrintf("tstLdr: Failed to close '%s' i=%d, rc=%Rrc.\n", pszFilename, i, rc);
262 rcRet++;
263 }
264 }
265 }
266
267 return rcRet;
268}
269
270
271
272int main(int argc, char **argv)
273{
274 RTR3Init();
275
276 int rcRet = 0;
277 if (argc <= 1)
278 {
279 RTPrintf("usage: %s <module> [more modules]\n", argv[0]);
280 return 1;
281 }
282
283 /*
284 * Iterate the files.
285 */
286 for (int argi = 1; argi < argc; argi++)
287 {
288 if (argv[argi][0] == '-' && argv[argi][1] == 'n')
289 g_fDontBitchOnResolveFailure = true;
290 else
291 {
292 RTPrintf("tstLdr: TESTING '%s'...\n", argv[argi]);
293 rcRet += testLdrOne(argv[argi]);
294 }
295 }
296
297 /*
298 * Test result summary.
299 */
300 if (!rcRet)
301 RTPrintf("tstLdr: SUCCESS\n");
302 else
303 RTPrintf("tstLdr: FAILURE - %d errors\n", rcRet);
304 return !!rcRet;
305}
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