source: trunk/kStuff/kLdr/tstkLdrMod.c

Last change on this file was 3601, checked in by bird, 18 years ago

license update.

  • Property svn:keywords set to Id
File size: 23.3 KB
RevLine 
[2878]1/* $Id: tstkLdrMod.c 3601 2007-10-29 00:21:13Z bird $ */
[2859]2/** @file
3 * kLdr - Module interpreter testcase.
[3601]4 */
5
6/*
7 * Copyright (c) 2006-2007 knut st. osmundsen <bird-kStuff-spam@anduin.net>
[2859]8 *
[3601]9 * This file is part of kStuff.
[2859]10 *
[3601]11 * kStuff is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
[2859]15 *
[3601]16 * In addition to the permissions in the GNU Lesser General Public
17 * License, you are granted unlimited permission to link the compiled
18 * version of this file into combinations with other programs, and to
19 * distribute those combinations without any restriction coming from
20 * the use of this file.
[2859]21 *
[3601]22 * kStuff is distributed in the hope that it will be useful,
[2859]23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
[3601]24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * Lesser General Public License for more details.
[2859]26 *
[3601]27 * You should have received a copy of the GNU Lesser General Public
28 * License along with kStuff; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 * 02110-1301, USA
[2859]31 */
32
33/*******************************************************************************
34* Header Files *
35*******************************************************************************/
[3570]36#include <k/kLdr.h>
[3579]37#include <k/kErr.h>
38#include <k/kErrors.h>
39
[2859]40#include <stdarg.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44
45
46/*******************************************************************************
47* Defined Constants And Macros *
48*******************************************************************************/
49/** The default base address used in the tests. */
[2861]50#define MY_BASEADDRESS 0x2400000
[2859]51
52
53/*******************************************************************************
54* Global Variables *
55*******************************************************************************/
56/** The numbers of errors. */
57static int g_cErrors = 0;
58
59
60
61/**
62 * Report failure.
63 */
64static int Failure(const char *pszFormat, ...)
65{
66 va_list va;
67
68 g_cErrors++;
69
70 printf("tstLdrMod: ");
71 va_start(va, pszFormat);
72 vprintf(pszFormat, va);
73 va_end(va);
74 printf("\n");
75 return 1;
76}
77
78
[2861]79/** Dummy import resolver callback. */
[3567]80static int BasicTestsGetImport(PKLDRMOD pMod, KU32 iImport, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol,
81 const char *pszVersion, PKLDRADDR puValue, KU32 *pfKind, void *pvUser)
[2861]82{
83 *puValue = 0xdeadface;
84 *pfKind = KLDRSYMKIND_NO_BIT | KLDRSYMKIND_NO_TYPE;
85 return 0;
86}
87
88
[2890]89/**
90 * Verbose memcmp().
91 */
[3567]92static int TestMemComp(const void *pv1, const void *pv2, KSIZE cb)
[2890]93{
[3567]94 KSIZE off;
95 const KU8 *pb1 = (const KU8 *)pv1;
96 const KU8 *pb2 = (const KU8 *)pv2;
[2890]97 if (!memcmp(pb1, pb2, cb))
98 return 0;
99 printf("Mismatching blocks pv1=%p pv2=%p cb=%#x:\n", pv1, pv2, cb);
100 for (off = 0; off < cb; off++)
101 {
102 if (pb1[off] == pb2[off])
103 continue;
104 printf("%08x %02x != %02x\n", off, pb1[off], pb2[off]);
105 }
106 return memcmp(pb1, pb2, cb); /* lazy */
107}
[2861]108
[2890]109
[2859]110/**
[2861]111 * Performs basic relocation tests.
112 */
113static int BasicTestsRelocate(PKLDRMOD pMod, void *pvBits, void *pvBits2)
114{
[3567]115 const KSIZE cbImage = (KSIZE)kLdrModSize(pMod);
[2861]116 int rc;
117
118 printf("* Relocation test...\n");
119
120 /*
121 * Get the same bits again to check that we get the same result.
122 */
123 memset(pvBits2, 0xfe, cbImage);
[3567]124 rc = kLdrModGetBits(pMod, pvBits2, (KUPTR)pvBits, BasicTestsGetImport, NULL);
[2861]125 if (rc)
[3579]126 return Failure("failed to get image bits, rc=%d (%s) (a)", rc, kErrName(rc));
[2890]127 if (TestMemComp(pvBits2, pvBits, cbImage))
[2861]128 return Failure("relocation test failed, mismatching bits (a)");
129
130 /*
131 * Short relocation round trip.
132 */
[3567]133 rc = kLdrModRelocateBits(pMod, pvBits2, 0x1000, (KUPTR)pvBits, BasicTestsGetImport, NULL);
[2861]134 if (rc)
[3579]135 return Failure("failed to relocate, rc=%d (%s) (b1)", rc, kErrName(rc));
[3567]136 rc = kLdrModRelocateBits(pMod, pvBits2, (KUPTR)pvBits, 0x1000, BasicTestsGetImport, NULL);
[2861]137 if (rc)
[3579]138 return Failure("failed to relocate, rc=%d (%s) (b2)", rc, kErrName(rc));
[2890]139 if (TestMemComp(pvBits2, pvBits, cbImage))
[2861]140 return Failure("relocation test failed, mismatching bits (b)");
141
142 /*
143 * Longer trip where we also check the intermediate results.
144 */
145 /* stage one */
[3567]146 rc = kLdrModRelocateBits(pMod, pvBits, 0x1000000, (KUPTR)pvBits, BasicTestsGetImport, NULL);
[2861]147 if (rc)
[3579]148 return Failure("failed to relocate, rc=%d (%s) (c1)", rc, kErrName(rc));
[2861]149 memset(pvBits2, 0xfe, cbImage);
150 rc = kLdrModGetBits(pMod, pvBits2, 0x1000000, BasicTestsGetImport, NULL);
151 if (rc)
[3579]152 return Failure("failed to get image bits, rc=%d (%s) (c1)", rc, kErrName(rc));
[2890]153 if (TestMemComp(pvBits2, pvBits, cbImage))
[2861]154 return Failure("relocation test failed, mismatching bits (c1)");
155
156 /* stage two */
[3567]157 rc = kLdrModRelocateBits(pMod, pvBits, ~(KUPTR)0x1010000, 0x1000000, BasicTestsGetImport, NULL);
[2861]158 if (rc)
[3579]159 return Failure("failed to relocate, rc=%d (%s) (c2)", rc, kErrName(rc));
[2861]160 memset(pvBits2, 0xef, cbImage);
[3567]161 rc = kLdrModGetBits(pMod, pvBits2, ~(KUPTR)0x1010000, BasicTestsGetImport, NULL);
[2861]162 if (rc)
[3579]163 return Failure("failed to get image bits, rc=%d (%s) (c2)", rc, kErrName(rc));
[2890]164 if (TestMemComp(pvBits2, pvBits, cbImage))
[2861]165 return Failure("relocation test failed, mismatching bits (c2)");
166
167 /* stage three */
[3567]168 rc = kLdrModRelocateBits(pMod, pvBits, MY_BASEADDRESS, ~(KUPTR)0x1010000, BasicTestsGetImport, NULL);
[2861]169 if (rc)
[3579]170 return Failure("failed to relocate, rc=%d (%s) (c3)", rc, kErrName(rc));
[2861]171 memset(pvBits2, 0xef, cbImage);
172 rc = kLdrModGetBits(pMod, pvBits2, MY_BASEADDRESS, BasicTestsGetImport, NULL);
173 if (rc)
[3579]174 return Failure("failed to get image bits, rc=%d (%s) (c3)", rc, kErrName(rc));
[2890]175 if (TestMemComp(pvBits2, pvBits, cbImage))
[2861]176 return Failure("relocation test failed, mismatching bits (c3)");
177
178 /* stage four */
[3567]179 rc = kLdrModRelocateBits(pMod, pvBits, ~(KUPTR)0 / 2 - 0x10000, MY_BASEADDRESS, BasicTestsGetImport, NULL);
[2861]180 if (rc)
[3579]181 return Failure("failed to relocate, rc=%d %(s) (c4)", rc, kErrName(rc));
[2861]182 memset(pvBits2, 0xdc, cbImage);
[3567]183 rc = kLdrModGetBits(pMod, pvBits2, ~(KUPTR)0 / 2 - 0x10000, BasicTestsGetImport, NULL);
[2861]184 if (rc)
[3579]185 return Failure("failed to get image bits, rc=%d (%s) (c4)", rc, kErrName(rc));
[2890]186 if (TestMemComp(pvBits2, pvBits, cbImage))
[2861]187 return Failure("relocation test failed, mismatching bits (c4)");
188
189 /* return */
[3567]190 rc = kLdrModRelocateBits(pMod, pvBits, (KUPTR)pvBits, ~(KUPTR)0 / 2 - 0x10000, BasicTestsGetImport, NULL);
[2861]191 if (rc)
[3579]192 return Failure("failed to relocate, rc=%d (%s) (c5)", rc, kErrName(rc));
[2861]193 memset(pvBits2, 0xcd, cbImage);
[3567]194 rc = kLdrModGetBits(pMod, pvBits2, (KUPTR)pvBits, BasicTestsGetImport, NULL);
[2861]195 if (rc)
[3579]196 return Failure("failed to get image bits, rc=%d (%s) (c5)", rc, kErrName(rc));
[2890]197 if (TestMemComp(pvBits2, pvBits, cbImage))
[2861]198 return Failure("relocation test failed, mismatching bits (c5)");
199
200 return 0;
201}
202
203
204/**
[2859]205 * Dump symbols and check that we can query each of them recursivly.
206 */
[3567]207static int BasicTestsEnumSymCallback(PKLDRMOD pMod, KU32 iSymbol, const char *pchSymbol, KSIZE cchSymbol,
208 const char *pszVersion, KLDRADDR uValue, KU32 fKind, void *pvUser)
[2859]209{
210 KLDRADDR uValue2;
[3567]211 KU32 fKind2;
[2859]212 int rc;
213
214 /* dump */
215 printf("#0x%08x: %016" PRI_KLDRADDR " %#08x", iSymbol, uValue, fKind);
[2899]216 if (pchSymbol)
217 printf(" %.*s", cchSymbol, pchSymbol);
[2859]218 printf("\n");
219
220 /* query by ordinal */
221 if (iSymbol != NIL_KLDRMOD_SYM_ORDINAL)
222 {
[2959]223 fKind2 = 0;
[2899]224 rc = kLdrModQuerySymbol(pMod, pvUser, MY_BASEADDRESS, iSymbol, NULL, 0, NULL, NULL, NULL,
[2859]225 &uValue2, &fKind2);
226 if (rc)
[3579]227 return Failure("Couldn't find symbol %#x (%.*s) by ordinal. rc=%d (%s)", iSymbol, cchSymbol, pchSymbol, rc, kErrName(rc));
[2859]228 if (uValue != uValue2)
[2899]229 return Failure("Symbol %#x (%.*s): Value mismatch %016" PRI_KLDRADDR " != %016" PRI_KLDRADDR " (enum!=query/ord) pvBits=%p",
230 iSymbol, cchSymbol, pchSymbol, uValue, uValue2, pvUser);
[2859]231 if (fKind != fKind2)
[2899]232 return Failure("Symbol %#x (%.*s): Kind mismatch %#x != %#x (enum!=query/ord) pvBits=%p",
233 iSymbol, cchSymbol, pchSymbol, fKind, fKind2, pvUser);
[2859]234 }
235
236 /* query by name. */
[2899]237 if (pchSymbol)
[2859]238 {
[2959]239 fKind2 = 0;
[2899]240 rc = kLdrModQuerySymbol(pMod, pvUser, MY_BASEADDRESS, NIL_KLDRMOD_SYM_ORDINAL, pchSymbol, cchSymbol, pszVersion,
241 NULL, NULL, &uValue2, &fKind2);
[2859]242 if (rc)
[3579]243 return Failure("Couldn't find symbol %#x (%.*s) by name. rc=%d (%s)", iSymbol, cchSymbol, pchSymbol, rc, kErrName(rc));
[2859]244 if (uValue != uValue2)
[2899]245 return Failure("Symbol %#x (%.*s): Value mismatch %016" PRI_KLDRADDR " != %016" PRI_KLDRADDR " (enum!=query/name) pvBits=%p",
246 iSymbol, cchSymbol, pchSymbol, uValue, uValue2, pvUser);
[2859]247 if (fKind != fKind2)
[2899]248 return Failure("Symbol %#x (%.*s): Kind mismatch %#x != %#x (enum!=query/name) pvBits=%p",
249 iSymbol, cchSymbol, pchSymbol, fKind, fKind2, pvUser);
[2859]250 }
251
252 return 0;
253}
254
255
256/**
257 * Dump debugger information and check it for correctness.
258 */
[3567]259static int BasicTestEnumDbgInfoCallback(PKLDRMOD pMod, KU32 iDbgInfo, KLDRDBGINFOTYPE enmType,
260 KI16 iMajorVer, KI16 iMinorVer, KLDRFOFF offFile, KLDRADDR LinkAddress,
[2859]261 KLDRSIZE cb, const char *pszExtFile, void *pvUser)
262{
263 printf("#0x%08x: enmType=%d %d.%d offFile=0x%" PRI_KLDRADDR " LinkAddress=%" PRI_KLDRADDR " cb=%" PRI_KLDRSIZE " pvUser=%p\n",
264 iDbgInfo, enmType, iMajorVer, iMinorVer, (KLDRADDR)offFile, LinkAddress, cb, pvUser);
265 if (pszExtFile)
266 printf(" pszExtFile=%p '%s'\n", pszExtFile, pszExtFile);
267
268 if (enmType >= KLDRDBGINFOTYPE_END || enmType <= KLDRDBGINFOTYPE_INVALID)
269 return Failure("Bad enmType");
270 if (pvUser != NULL)
271 return Failure("pvUser");
272
273 return 0;
274}
275
276
277/**
278 * Performs the basic module loader test on the specified module and image bits.
279 */
280static int BasicTestsSub2(PKLDRMOD pMod, void *pvBits)
281{
[3567]282 KI32 cImports;
283 KI32 i;
[2859]284 int rc;
[3567]285 KU32 fKind;
[2859]286 KLDRADDR Value;
287 KLDRADDR MainEPAddress;
288 KLDRSTACKINFO StackInfo;
289
[2861]290 printf("* Testing queries with pvBits=%p...\n", pvBits);
291
[2859]292 /*
293 * Get the import modules.
294 */
295 cImports = kLdrModNumberOfImports(pMod, pvBits);
296 printf("cImports=%d\n", cImports);
297 if (cImports < 0)
[2861]298 return Failure("failed to query the number of import, cImports=%d", cImports);
[2859]299 for (i = 0; i < cImports; i++)
300 {
301 char szImportModule[260];
302 rc = kLdrModGetImport(pMod, pvBits, i, szImportModule, sizeof(szImportModule));
303 if (rc)
[3579]304 return Failure("failed to get import module name, rc=%d (%s). (%.260s)", rc, kErrName(rc), szImportModule);
[2859]305 printf("import #%d: '%s'\n", i, szImportModule);
306 }
307
308 /*
309 * Query stack info.
310 */
311 StackInfo.Address = ~(KLDRADDR)42;
312 StackInfo.LinkAddress = ~(KLDRADDR)42;
313 StackInfo.cbStack = ~(KLDRSIZE)42;
314 StackInfo.cbStackThread = ~(KLDRSIZE)42;
315 rc = kLdrModGetStackInfo(pMod, pvBits, MY_BASEADDRESS, &StackInfo);
316 if (rc)
[3579]317 return Failure("kLdrModGetStackInfo failed with rc=%d (%s)", rc, kErrName(rc));
[2859]318 printf("Stack: Address=%016" PRI_KLDRADDR " LinkAddress=%016" PRI_KLDRADDR "\n"
319 " cbStack=%016" PRI_KLDRSIZE " cbStackThread=%016" PRI_KLDRSIZE "\n",
320 StackInfo.Address, StackInfo.LinkAddress, StackInfo.cbStack, StackInfo.cbStackThread);
321 if (StackInfo.Address == ~(KLDRADDR)42)
322 return Failure("Bad StackInfo.Address");
323 if (StackInfo.LinkAddress == ~(KLDRADDR)42)
324 return Failure("Bad StackInfo.LinkAddress");
325 if (StackInfo.cbStack == ~(KLDRSIZE)42)
326 return Failure("Bad StackInfo.cbStack");
327 if (StackInfo.cbStackThread == ~(KLDRSIZE)42)
328 return Failure("Bad StackInfo.cbStackThread");
329
330 /*
331 * Query entrypoint.
332 */
333 MainEPAddress = ~(KLDRADDR)42;
334 rc = kLdrModQueryMainEntrypoint(pMod, pvBits, MY_BASEADDRESS, &MainEPAddress);
335 if (rc)
[3579]336 return Failure("kLdrModQueryMainEntrypoint failed with rc=%d (%s)", rc, kErrName(rc));
[2859]337 printf("Entrypoint: %016" PRI_KLDRADDR "\n", MainEPAddress);
338 if (MainEPAddress == ~(KLDRADDR)42)
339 return Failure("MainEPAddress wasn't set.");
[2861]340 if (MainEPAddress != NIL_KLDRADDR && MainEPAddress < MY_BASEADDRESS)
341 return Failure("Bad MainEPAddress (a).");
342 if (MainEPAddress != NIL_KLDRADDR && MainEPAddress >= MY_BASEADDRESS + kLdrModSize(pMod))
343 return Failure("Bad MainEPAddress (b).");
[2859]344
345 /*
346 * Debugger information.
347 */
348 rc = kLdrModHasDbgInfo(pMod, pvBits);
349 if (!rc)
350 printf("Has Debugger Information\n");
351 else if (rc == KLDR_ERR_NO_DEBUG_INFO)
352 printf("NO Debugger Information\n");
353 else
[3579]354 return Failure("kLdrModHasDbgInfo failed with rc=%d (%s)", rc, kErrName(rc));
[2859]355 rc = kLdrModEnumDbgInfo(pMod, pvBits, BasicTestEnumDbgInfoCallback, NULL);
356 if (rc)
[3579]357 return Failure("kLdrModEnumDbgInfo failed with rc=%d (%s)", rc, kErrName(rc));
[2859]358
359
360 /*
361 * Negative symbol query tests.
362 */
[2959]363 fKind = 0;
[2859]364 Value = 0x0badc0de;
[2899]365 rc = kLdrModQuerySymbol(pMod, pvBits, MY_BASEADDRESS, NIL_KLDRMOD_SYM_ORDINAL - 20, NULL, 0, NULL, NULL, NULL,
[2859]366 &Value, &fKind);
367 if (rc)
368 {
369 if (Value != 0)
370 return Failure("Value wasn't cleared on failure.");
371 }
372
[2959]373 fKind = 0;
[2859]374 Value = 0x0badc0de;
[2899]375 rc = kLdrModQuerySymbol(pMod, pvBits, MY_BASEADDRESS, NIL_KLDRMOD_SYM_ORDINAL, NULL, 0, NULL, NULL, NULL,
[2859]376 &Value, &fKind);
377 if (!rc)
378 return Failure("NIL ordinal succeeded!");
379 if (Value != 0)
380 return Failure("Value wasn't cleared on failure.");
381
382 /*
383 * Enumerate and query all symbols.
384 */
385 printf("\n"
386 "Symbols:\n");
387 rc = kLdrModEnumSymbols(pMod, pvBits, MY_BASEADDRESS, 0, BasicTestsEnumSymCallback, pvBits);
388 if (rc)
[3579]389 return Failure("kLdrModEnumSymbols failed with rc=%d (%s)", rc, kErrName(rc));
[2859]390
391
[3585]392/*int kLdrModCanExecuteOn(PKLDRMOD pMod, const void *pvBits, KCPUARCH enmArch, KCPU enmCpu);
[2859]393*/
394
395 return 0;
396}
397
398
399/**
400 * Performs the basic module loader test on the specified module
401 */
402static int BasicTestsSub(PKLDRMOD pMod)
403{
404 int rc;
[3567]405 KU32 i;
[2859]406 void *pvBits;
[3567]407 KSIZE cbImage;
[2859]408
409 /*
410 * Check/dump the module structure.
411 */
[2899]412 printf("pMod=%p u32Magic=%#x cSegments=%d\n", (void *)pMod, pMod->u32Magic, pMod->cSegments);
[2859]413 printf("enmType=%d enmFmt=%d enmArch=%d enmCpu=%d enmEndian=%d\n",
414 pMod->enmType, pMod->enmFmt, pMod->enmArch, pMod->enmCpu, pMod->enmEndian);
415 printf("Filename: %s (%d bytes)\n", pMod->pszFilename, pMod->cchFilename);
416 printf(" Name: %s (%d bytes)\n", pMod->pszName, pMod->cchName);
417 printf("\n");
418
419 if (pMod->u32Magic != KLDRMOD_MAGIC)
420 return Failure("Bad u32Magic");
421 if (strlen(pMod->pszFilename) != pMod->cchFilename)
422 return Failure("Bad cchFilename");
423 if (strlen(pMod->pszName) != pMod->cchName)
424 return Failure("Bad cchName");
425 if (pMod->enmFmt >= KLDRFMT_END || pMod->enmFmt <= KLDRFMT_INVALID)
426 return Failure("Bad enmFmt");
427 if (pMod->enmType >= KLDRTYPE_END || pMod->enmType <= KLDRTYPE_INVALID)
428 return Failure("Bad enmType: %d", pMod->enmType);
[3585]429 if (!K_ARCH_IS_VALID(pMod->enmArch))
[2859]430 return Failure("Bad enmArch");
[3585]431 if (pMod->enmCpu >= KCPU_END || pMod->enmCpu <= KCPU_INVALID)
[2859]432 return Failure("Bad enmCpu");
433 if (pMod->enmEndian >= KLDRENDIAN_END || pMod->enmEndian <= KLDRENDIAN_INVALID)
434 return Failure("Bad enmEndian");
435
436 for (i = 0; i < pMod->cSegments; i++)
437 {
438 printf("seg #%d: pvUser=%p enmProt=%d Name: '%.*s' (%d bytes)\n",
439 i, pMod->aSegments[i].pvUser, pMod->aSegments[i].enmProt,
440 pMod->aSegments[i].cchName, pMod->aSegments[i].pchName, pMod->aSegments[i].cchName);
441 printf("LinkAddress: %016" PRI_KLDRADDR " cb: %016" PRI_KLDRSIZE " Alignment=%08" PRI_KLDRADDR " \n",
442 pMod->aSegments[i].LinkAddress, pMod->aSegments[i].cb, pMod->aSegments[i].Alignment);
443 printf(" RVA: %016" PRI_KLDRADDR " cbMapped: %016" PRI_KLDRSIZE " MapAddress=%p\n",
[2899]444 pMod->aSegments[i].RVA, (KLDRSIZE)pMod->aSegments[i].cbMapped, (void *)pMod->aSegments[i].MapAddress);
[2859]445 printf(" offFile: %016" PRI_KLDRADDR " cbFile: %016" PRI_KLDRSIZE "\n",
446 (KLDRADDR)pMod->aSegments[i].offFile, (KLDRSIZE)pMod->aSegments[i].cbFile);
447 printf("\n");
448
449 if (pMod->aSegments[i].pvUser != NULL)
450 return Failure("Bad pvUser");
[3571]451 if (pMod->aSegments[i].enmProt >= KPROT_END || pMod->aSegments[i].enmProt <= KPROT_INVALID)
[2859]452 return Failure("Bad enmProt");
453 if (pMod->aSegments[i].MapAddress != 0)
454 return Failure("Bad MapAddress");
455 if (pMod->aSegments[i].cbMapped < pMod->aSegments[i].cb)
456 return Failure("Bad cbMapped (1)");
457 if (pMod->aSegments[i].cbMapped && !pMod->aSegments[i].Alignment)
458 return Failure("Bad cbMapped (2)");
459 if (pMod->aSegments[i].cbMapped > kLdrModSize(pMod))
460 return Failure("Bad cbMapped (3)");
461 if ( pMod->aSegments[i].Alignment
462 && (pMod->aSegments[i].RVA & (pMod->aSegments[i].Alignment - 1)))
463 return Failure("Bad RVA (1)");
464 if (pMod->aSegments[i].RVA != NIL_KLDRADDR && !pMod->aSegments[i].Alignment)
465 return Failure("Bad RVA (2)");
466 if ( pMod->aSegments[i].RVA != NIL_KLDRADDR
467 && pMod->aSegments[i].RVA >= kLdrModSize(pMod))
468 return Failure("Bad RVA (3)");
469 if ( pMod->aSegments[i].RVA != NIL_KLDRADDR
470 && pMod->aSegments[i].RVA + pMod->aSegments[i].cbMapped > kLdrModSize(pMod))
471 return Failure("Bad RVA/cbMapped (4)");
472 if (pMod->aSegments[i].LinkAddress != NIL_KLDRADDR && !pMod->aSegments[i].Alignment)
473 return Failure("Bad LinkAddress");
474 if ( pMod->aSegments[i].LinkAddress != NIL_KLDRADDR
475 && (pMod->aSegments[i].LinkAddress) & (pMod->aSegments[i].Alignment - 1))
476 return Failure("Bad LinkAddress alignment");
477 if (pMod->aSegments[i].offFile != -1 && pMod->aSegments[i].cbFile == -1)
478 return Failure("Bad offFile");
479 if (pMod->aSegments[i].offFile == -1 && pMod->aSegments[i].cbFile != -1)
480 return Failure("Bad cbFile");
481 }
482
[2861]483
[2859]484 /*
485 * Get image the size and query the image bits.
486 */
[2861]487 printf("* Testing user mapping...\n");
488
[3567]489 cbImage = (KSIZE)kLdrModSize(pMod);
[2859]490 if (cbImage != kLdrModSize(pMod))
[2861]491 return Failure("aborting test because the image is too huge!");
[3567]492 pvBits = malloc((KSIZE)cbImage);
[2859]493 if (!pvBits)
[2861]494 return Failure("failed to allocate %d bytes for the image", cbImage);
[2859]495
[3567]496 rc = kLdrModGetBits(pMod, pvBits, (KUPTR)pvBits, BasicTestsGetImport, NULL);
[2859]497 if (rc)
[3579]498 return Failure("failed to get image bits, rc=%d (%s)", rc, kErrName(rc));
[2859]499
500 /*
501 * Another cleanup nesting.
502 */
503 rc = BasicTestsSub2(pMod, pvBits);
[2861]504 if (!rc)
505 {
506 /*
507 * Test relocating the bits in a few different ways before we're done with them.
508 */
[3567]509 void *pvBits2 = malloc((KSIZE)cbImage);
[2861]510 if (pvBits2)
511 {
512 rc = BasicTestsRelocate(pMod, pvBits, pvBits2);
513 free(pvBits2);
514 }
515 else
516 rc = Failure("failed to allocate %d bytes for the 2nd image", cbImage);
517 }
518
[2859]519 free(pvBits);
520 return rc;
521}
522
523
524/**
[2861]525 * Tests the mapping related api, after mapping.
526 */
527static int BasicTestsSubMap2(PKLDRMOD pMod)
528{
529 int rc;
530
531 rc = kLdrModFixupMapping(pMod, BasicTestsGetImport, NULL);
532 if (rc)
[3579]533 return Failure("kLdrModFixupMapping (a) failed, rc=%d (%s)", rc, kErrName(rc));
[2861]534
535 rc = kLdrModReload(pMod);
536 if (rc)
[3579]537 return Failure("kLdrModReload (a) failed, rc=%d (%s)", rc, kErrName(rc));
[2861]538
539 rc = kLdrModReload(pMod);
540 if (rc)
[3579]541 return Failure("kLdrModReload (b) failed, rc=%d (%s)", rc, kErrName(rc));
[2861]542
543 rc = kLdrModFixupMapping(pMod, BasicTestsGetImport, NULL);
544 if (rc)
[3579]545 return Failure("kLdrModFixupMapping (b) failed, rc=%d (%s)", rc, kErrName(rc));
[2861]546
547 rc = kLdrModAllocTLS(pMod);
548 if (rc)
[3579]549 return Failure("kLdrModAllocTLS (a) failed, rc=%d (%s)", rc, kErrName(rc));
[2861]550 kLdrModFreeTLS(pMod);
551
552 rc = kLdrModAllocTLS(pMod);
553 if (rc)
[3579]554 return Failure("kLdrModAllocTLS (b) failed, rc=%d (%s)", rc, kErrName(rc));
[2861]555 kLdrModFreeTLS(pMod);
556
557 /*
558 * Repeat the BasicTestsSub2 with pvBits as NULL to test module
559 * interpreters that can utilize the mapping.
560 */
561 rc = BasicTestsSub2(pMod, NULL);
562 if (rc)
[3579]563 return Failure("BasicTestsSub2 in Map2 failed, rc=%d (%s)", rc, kErrName(rc));
[2861]564 return 0;
565}
566
567
568/**
[2860]569 * Tests the mapping related api.
570 */
571static int BasicTestsSubMap(PKLDRMOD pMod)
572{
[2861]573 int rc, rc2;
574 printf("* Mapping tests...\n");
[2860]575
576 rc = kLdrModMap(pMod);
577 if (rc)
[3579]578 return Failure("kLdrModMap failed, rc=%d (%s)", rc, kErrName(rc));
[2861]579 rc = BasicTestsSubMap2(pMod);
580 rc2 = kLdrModUnmap(pMod);
581 if (rc2)
582 {
[3579]583 Failure("kLdrModUnmap failed, rc=%d (%s)", rc2, kErrName(rc2));
[2861]584 rc = rc ? rc : rc2;
585 }
[2860]586
[2861]587 printf("* Mapping tests done.\n");
588 return rc;
[2860]589}
590
591
592/**
[2859]593 * Performs basic module loader tests on the specified file.
594 */
595static int BasicTests(const char *pszFilename)
596{
597 PKLDRMOD pMod;
598 int rc, rc2;
599
[2861]600 printf("tstLdrMod: Testing '%s'", pszFilename);
[2859]601 rc = kLdrModOpen(pszFilename, &pMod);
602 if (!rc)
603 {
604 rc = BasicTestsSub(pMod);
[2860]605 if (!rc)
606 rc = BasicTestsSubMap(pMod);
[2861]607 if (!rc)
608 rc = BasicTestsSub2(pMod, NULL);
[2859]609 rc2 = kLdrModClose(pMod);
610 if (rc2)
[3579]611 Failure("failed to close '%s', rc=%d (%s)", pszFilename, rc, kErrName(rc));
[2859]612 if (rc2 && !rc)
613 rc = rc2;
614 }
615 else
[3579]616 Failure("Failed to open '%s', rc=%d (%s)", pszFilename, rc, kErrName(rc));
[2859]617 return rc ? 1 : 0;
618}
619
620
621int main(int argc, char **argv)
622{
623 BasicTests(argv[argc-1]);
624
625 if (!g_cErrors)
626 printf("tstLdrMod: SUCCESS\n");
627 else
628 printf("tstLdrMod: FAILURE - %d errors\n", g_cErrors);
629 return !!g_cErrors;
630}
631
Note: See TracBrowser for help on using the repository browser.