Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1158 lines
25 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. genxx.c
  5. Abstract:
  6. This module implements a program which generates structure offset
  7. definitions for kernel structures that are accessed in assembly code.
  8. Author:
  9. Forrest C. Foltz (forrestf) 20-Jan-98
  10. To use:
  11. This program reads an OBJ file generated by the target platform's
  12. compiler.
  13. To generate such an OBJ, go to ke\up and do a "nmake UMAPPL=gen<plt>",
  14. where <plt> is a platform identifier like i386, etc.
  15. All you need from this latter step is the OBJ, the link phase will not
  16. succeed which is fine.
  17. Revision History:
  18. --*/
  19. #include <windows.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #define SKIP_M4
  23. #include <genxx.h>
  24. //
  25. // Internal structure definitions, macros, constants
  26. //
  27. #define ARRAY_SIZE( x ) (sizeof( x ) / sizeof( (x)[0] ))
  28. typedef struct _OUTPUT_FILE *POUTPUT_FILE;
  29. typedef struct _OUTPUT_FILE {
  30. POUTPUT_FILE Next;
  31. ULONG EnableMask;
  32. BOOLEAN IncFormat;
  33. FILE *File;
  34. } OUTPUT_FILE;
  35. //
  36. // Function prototypes follow
  37. //
  38. VOID
  39. ApplyFixupsToImage( VOID );
  40. VOID
  41. BuildHeaderFiles(
  42. STRUC_ELEMENT UNALIGNED *StrucArray
  43. );
  44. VOID
  45. __cdecl
  46. CheckCondition(
  47. int Condition,
  48. const char *format,
  49. ...
  50. );
  51. VOID
  52. AddNewOutputFile(
  53. PUCHAR RootRelativePath,
  54. ULONG Flags
  55. );
  56. VOID
  57. AddNewAbsoluteOutputFile(
  58. PUCHAR AbsolutePath,
  59. ULONG Flags
  60. );
  61. VOID
  62. CloseOutputFiles( VOID );
  63. VOID
  64. _cdecl
  65. HeaderPrint(
  66. ULONG EnableFlags,
  67. ULONG Type,
  68. ...
  69. );
  70. PSTRUC_ELEMENT
  71. FindStructureElementArray(
  72. PCHAR Buffer,
  73. ULONG BufferSize
  74. );
  75. VOID
  76. GetEnvironment( VOID );
  77. PSTRUC_ELEMENT
  78. LoadObjImage(
  79. PUCHAR ImagePath
  80. );
  81. PCHAR
  82. StripWhiteSpace(
  83. PCHAR String
  84. );
  85. VOID
  86. Usage( VOID );
  87. //
  88. // Constant tables follow
  89. //
  90. const char *PreprocessedFormatStringArray[] = {
  91. // SEF_EQUATE
  92. "#define %s 0x%0x\n",
  93. // SEF_EQUATE64
  94. "#define %s 0x%016I64x\n",
  95. // SEF_COMMENT
  96. "\n"
  97. "//\n"
  98. "// %s\n"
  99. "//\n"
  100. "\n",
  101. // SEF_STRING
  102. "%s\n",
  103. // SEF_BITFLD
  104. "#define %s_MASK 0x%I64x\n"
  105. "#define %s 0x%0x\n",
  106. // SEF_BITALIAS
  107. "#define %s 0x%0x\n",
  108. // SEF_STRUCTURE
  109. "struct %s {\n"
  110. " UCHAR fill[ %d ];\n"
  111. "}; // %s\n"
  112. };
  113. const char *Asm386FormatStringArray[] = {
  114. // SEF_EQUATE
  115. "%s equ 0%04XH\n",
  116. // SEF_EQUATE64
  117. "%s equ 0%016I64XH\n",
  118. // SEF_COMMENT
  119. "\n"
  120. ";\n"
  121. "; %s\n"
  122. ";\n"
  123. "\n",
  124. // SEF_STRING
  125. "%s",
  126. // SEF_BITFLD
  127. "%s_MASK equ 0%I64XH\n"
  128. "%s equ 0%0XH\n",
  129. // SEF_BITALIAS
  130. "%s equ 0%08XH\n",
  131. // SEF_STRUCTURE
  132. "%s struc\n"
  133. " db %d dup(0)\n"
  134. "%s ends\n"
  135. };
  136. //
  137. // Each platform contains a list of generated header files.
  138. //
  139. typedef struct {
  140. PCHAR HeaderPath;
  141. ULONG Flags;
  142. } HEADERPATH, *PHEADERPATH;
  143. HEADERPATH HeaderListi386[] = {
  144. { "public\\sdk\\inc\\ks386.inc", SEF_KERNEL | SEF_INC_FORMAT },
  145. { "base\\ntos\\inc\\hal386.inc", SEF_HAL | SEF_INC_FORMAT },
  146. { NULL, 0 }
  147. };
  148. HEADERPATH HeaderListIa64[] = {
  149. { "public\\sdk\\inc\\ksia64.h", SEF_KERNEL | SEF_H_FORMAT },
  150. { "base\\ntos\\inc\\halia64.h", SEF_HAL | SEF_H_FORMAT },
  151. { NULL, 0 }
  152. };
  153. HEADERPATH HeaderListVdm[] = {
  154. { "public\\internal\\base\\inc\\vdmtib.inc", SEF_INC_FORMAT },
  155. { NULL, 0 }
  156. };
  157. HEADERPATH HeaderListAmd64[] = {
  158. { "public\\sdk\\inc\\ksamd64.inc", SEF_KERNEL | SEF_INC_FORMAT },
  159. { "base\\ntos\\inc\\halamd64.inc", SEF_HAL | SEF_INC_FORMAT },
  160. { NULL, 0 }
  161. };
  162. typedef struct {
  163. PCHAR PlatformName;
  164. PCHAR ObjPath;
  165. PHEADERPATH HeaderPathList;
  166. } PLATFORM, *PPLATFORM;
  167. PLATFORM PlatformList[] = {
  168. { "i386",
  169. "base\\ntos\\ke\\up\\obj\\i386\\geni386.obj",
  170. HeaderListi386 },
  171. { "ia64",
  172. "base\\ntos\\ke\\up\\obj\\ia64\\genia64.obj",
  173. HeaderListIa64 },
  174. { "vdm",
  175. "base\\ntos\\vdm\\up\\obj\\i386\\genvdm.obj",
  176. HeaderListVdm },
  177. { "amd64",
  178. "base\\ntos\\ke\\up\\obj\\amd64\\genamd64.obj",
  179. HeaderListAmd64 },
  180. { NULL, NULL, NULL }
  181. };
  182. const char MarkerString[] = MARKER_STRING;
  183. //
  184. // Global vars follow
  185. //
  186. POUTPUT_FILE OutputFileList;
  187. PCHAR ObjImage;
  188. CHAR HalHeaderPath[ MAX_PATH ];
  189. CHAR KernelHeaderPath[ MAX_PATH ];
  190. CHAR HeaderPath[ MAX_PATH ];
  191. CHAR ObjectPath[ MAX_PATH ];
  192. CHAR NtRoot[ MAX_PATH ];
  193. CHAR TempBuf[ MAX_PATH ];
  194. BOOL fOutputSpecified;
  195. BOOL fHalHeaderPath;
  196. BOOL fKernelHeaderPath;
  197. BOOL fIncFormat;
  198. //
  199. // The actual code...
  200. //
  201. int
  202. __cdecl
  203. main(
  204. int argc,
  205. char *argv[]
  206. )
  207. {
  208. int argNum;
  209. char *arg;
  210. int platformIndex;
  211. int fileIndex;
  212. BOOL validSwitch;
  213. PSTRUC_ELEMENT strucArray;
  214. PPLATFORM platform;
  215. PHEADERPATH headerPath;
  216. GetEnvironment();
  217. //
  218. // Assume no platform specified, then see if we can find one.
  219. //
  220. ObjectPath[ 0 ] = '\0';
  221. for( argNum = 1; argNum < argc; argNum++ ){
  222. validSwitch = FALSE;
  223. arg = argv[ argNum ];
  224. if( *arg == '/' || *arg == '-' ){
  225. //
  226. // A switch was passed. See what it is.
  227. //
  228. arg++;
  229. switch( *arg ){
  230. case 'o':
  231. //
  232. // Specified an output file
  233. //
  234. fOutputSpecified = TRUE;
  235. strcpy( HeaderPath, arg+1 );
  236. validSwitch = TRUE;
  237. break;
  238. case 's':
  239. //
  240. // Specified include file suffix (either 'h' or 'inc')
  241. //
  242. if( _stricmp( arg+1, "inc" ) == 0 ){
  243. //
  244. // We would like the "inc" format, thanks
  245. //
  246. fIncFormat = TRUE;
  247. } else {
  248. CheckCondition( _stricmp( arg+1, "h" ) == 0,
  249. "Invalid suffix option: -s[inc|h]\n");
  250. }
  251. validSwitch = TRUE;
  252. break;
  253. case 'k':
  254. //
  255. // Kernel header path. Save off.
  256. //
  257. fKernelHeaderPath = TRUE;
  258. strcpy( KernelHeaderPath, arg+1 );
  259. validSwitch = TRUE;
  260. break;
  261. case 'h':
  262. //
  263. // Hal header path. Save off.
  264. //
  265. fHalHeaderPath = TRUE;
  266. strcpy( HalHeaderPath, arg+1 );
  267. validSwitch = TRUE;
  268. break;
  269. default:
  270. //
  271. // Check our platform list.
  272. //
  273. platform = PlatformList;
  274. while( platform->PlatformName != NULL ){
  275. if( _stricmp( platform->PlatformName,
  276. arg ) == 0 ){
  277. //
  278. // Platform was specified, we will build the path to
  279. // the obj.
  280. //
  281. sprintf( ObjectPath,
  282. "%s\\%s",
  283. NtRoot,
  284. platform->ObjPath );
  285. //
  286. // Add the header paths too.
  287. //
  288. headerPath = platform->HeaderPathList;
  289. while( headerPath->HeaderPath != NULL ){
  290. if (fHalHeaderPath && (headerPath->Flags & SEF_HAL)) {
  291. strcpy(TempBuf, HalHeaderPath);
  292. AddNewAbsoluteOutputFile( HalHeaderPath, headerPath->Flags );
  293. } else
  294. if (fKernelHeaderPath && (headerPath->Flags & SEF_KERNEL)) {
  295. strcpy(TempBuf, KernelHeaderPath);
  296. AddNewAbsoluteOutputFile( KernelHeaderPath, headerPath->Flags );
  297. } else {
  298. AddNewOutputFile( headerPath->HeaderPath,
  299. headerPath->Flags );
  300. }
  301. headerPath++;
  302. }
  303. validSwitch = TRUE;
  304. break;
  305. }
  306. platform++;
  307. }
  308. break;
  309. }
  310. if( validSwitch == FALSE ){
  311. Usage();
  312. }
  313. } else {
  314. //
  315. // We are dealing with something that is not a switch. The only
  316. // possibility is the path to the object file.
  317. //
  318. strcpy( ObjectPath, arg );
  319. }
  320. }
  321. CheckCondition( ObjectPath[0] != '\0',
  322. "Object path not specified\n" );
  323. if( fOutputSpecified != FALSE ){
  324. //
  325. // The output path was specified
  326. //
  327. AddNewAbsoluteOutputFile( HeaderPath,
  328. fIncFormat ? SEF_INC_FORMAT : SEF_H_FORMAT );
  329. }
  330. strucArray = LoadObjImage( ObjectPath );
  331. BuildHeaderFiles( strucArray );
  332. CloseOutputFiles();
  333. //
  334. // Indicate success.
  335. //
  336. return 0;
  337. }
  338. VOID
  339. AddNewAbsoluteOutputFile(
  340. PUCHAR AbsolutePath,
  341. ULONG Flags
  342. )
  343. {
  344. POUTPUT_FILE outputFile;
  345. outputFile = malloc( sizeof( OUTPUT_FILE ));
  346. CheckCondition( outputFile != NULL, "Out of memory\n" );
  347. outputFile->EnableMask = (ULONG)(Flags & SEF_ENABLE_MASK);
  348. if( (Flags & SEF_INC_FORMAT_MASK) == SEF_INC_FORMAT ){
  349. //
  350. // This file will be created in '.inc' format for the 386 assembler.
  351. //
  352. outputFile->IncFormat = TRUE;
  353. } else {
  354. //
  355. // This file will be created in '.h' format for the standard C
  356. // preprocessor.
  357. //
  358. outputFile->IncFormat = FALSE;
  359. }
  360. outputFile->File = fopen( AbsolutePath, "w" );
  361. CheckCondition( outputFile->File != NULL,
  362. "Cannot open %s for writing.\n",
  363. TempBuf );
  364. printf("%s -> %s\n", ObjectPath, TempBuf );
  365. //
  366. // Link this structure into the list of output files
  367. //
  368. outputFile->Next = OutputFileList;
  369. OutputFileList = outputFile;
  370. }
  371. VOID
  372. AddNewOutputFile(
  373. PUCHAR RootRelativePath,
  374. ULONG Flags
  375. )
  376. {
  377. //
  378. // Create the canonoical file path and open the file.
  379. //
  380. sprintf( TempBuf,
  381. "%s\\%s",
  382. NtRoot,
  383. RootRelativePath );
  384. AddNewAbsoluteOutputFile( TempBuf, Flags );
  385. }
  386. VOID
  387. CloseOutputFiles( VOID )
  388. {
  389. POUTPUT_FILE outputFile;
  390. outputFile = OutputFileList;
  391. while( outputFile != NULL ){
  392. fclose( outputFile->File );
  393. outputFile = outputFile->Next;
  394. }
  395. }
  396. PSTRUC_ELEMENT
  397. LoadObjImage(
  398. PUCHAR ImagePath
  399. )
  400. {
  401. long objImageSize;
  402. int result;
  403. PSTRUC_ELEMENT strucArray;
  404. FILE * objFile;
  405. //
  406. // Open up and read the platform-specific .obj file.
  407. //
  408. objFile = fopen( ImagePath, "rb" );
  409. CheckCondition( objFile != NULL,
  410. "Cannot open %s for reading.\n"
  411. "This file must have been created by the compiler for the "
  412. "target platform.\n",
  413. ImagePath );
  414. //
  415. // Get the file size, allocate a buffer, read it in, and close.
  416. //
  417. result = fseek( objFile, 0, SEEK_END );
  418. CheckCondition( result == 0,
  419. "fseek() failed, error %d\n",
  420. errno );
  421. objImageSize = ftell( objFile );
  422. CheckCondition( objImageSize != -1L,
  423. "ftell() failed, error %d\n",
  424. errno );
  425. CheckCondition( objImageSize > 0,
  426. "%s appears to be corrupt\n",
  427. ImagePath );
  428. ObjImage = malloc( objImageSize );
  429. CheckCondition( ObjImage != NULL,
  430. "Out of memory\n" );
  431. result = fseek( objFile, 0, SEEK_SET );
  432. CheckCondition( result == 0,
  433. "fseek() failed, error %d\n",
  434. errno );
  435. result = fread( ObjImage, 1, objImageSize, objFile );
  436. CheckCondition( result == objImageSize,
  437. "Error reading from %s\n",
  438. ImagePath );
  439. fclose( objFile );
  440. //
  441. // Even though this is just an .obj file, we want it "fixed up"
  442. //
  443. ApplyFixupsToImage();
  444. //
  445. // Got the image, find the beginning of the array.
  446. //
  447. strucArray = FindStructureElementArray( ObjImage,
  448. objImageSize );
  449. CheckCondition( strucArray != NULL,
  450. "%s does not contain a structure description array.\n",
  451. ImagePath );
  452. return strucArray;
  453. }
  454. VOID
  455. BuildHeaderFiles(
  456. STRUC_ELEMENT UNALIGNED *StrucArray
  457. )
  458. {
  459. STRUC_ELEMENT UNALIGNED *strucArray;
  460. ULONG runningEnableMask;
  461. ULONG enableMask;
  462. ULONG sefType;
  463. const char *formatString;
  464. ULONG bitFieldStart;
  465. PUINT64 bitFieldPtr;
  466. UINT64 bitFieldData;
  467. PCHAR name;
  468. BOOLEAN finished;
  469. //
  470. // Process each element in the array. The first element is the
  471. // marker string element, so it is skipped.
  472. //
  473. runningEnableMask = 0;
  474. finished = FALSE;
  475. strucArray = StrucArray;
  476. do{
  477. strucArray++;
  478. sefType = (ULONG)(strucArray->Flags & SEF_TYPE_MASK);
  479. if( sefType == SEF_BITFLD ){
  480. //
  481. // For bitfields, the enable mask is set explicitly
  482. //
  483. enableMask = (ULONG)(strucArray->Flags & SEF_ENABLE_MASK);
  484. } else {
  485. //
  486. // For everything else, we use the current runningEnableMask
  487. //
  488. enableMask = runningEnableMask;
  489. }
  490. switch( sefType ){
  491. case SEF_BITFLD:
  492. //
  493. // This kind of element is tricky. "Equate" is actually a
  494. // pointer to a bitfield structure. This structure has had
  495. // a portion of it (the bitfield) initialized to ones.
  496. //
  497. // It is the job of this case to poke around in that
  498. // structure in order to determine where the bitfield landed.
  499. //
  500. bitFieldPtr = (PINT64)(strucArray->Equate);
  501. bitFieldData = *bitFieldPtr;
  502. //
  503. // Determine the zero-based starting bitnumber of the field.
  504. //
  505. bitFieldStart = 0;
  506. while( (bitFieldData & ((UINT64)1 << bitFieldStart)) == 0 ){
  507. bitFieldStart++;
  508. }
  509. name = StripWhiteSpace( strucArray->Name );
  510. if( *name != '\0'){
  511. HeaderPrint( enableMask,
  512. sefType,
  513. name,
  514. bitFieldData,
  515. name,
  516. bitFieldStart );
  517. }
  518. //
  519. // A bitfield can be followed by any number of
  520. // SEF_BITALIAS entries. These are alias names for the
  521. // bitmask that was just defined.
  522. //
  523. while( TRUE ){
  524. sefType = (ULONG)((strucArray+1)->Flags & SEF_TYPE_MASK);
  525. if( sefType != SEF_BITALIAS ){
  526. //
  527. // No more aliases.
  528. //
  529. break;
  530. }
  531. //
  532. // This is a bitmask alias field, process it.
  533. //
  534. strucArray++;
  535. name = StripWhiteSpace( strucArray->Name );
  536. HeaderPrint( enableMask,
  537. sefType,
  538. name,
  539. bitFieldData );
  540. }
  541. break;
  542. case SEF_END:
  543. finished = TRUE;
  544. break;
  545. case SEF_EQUATE:
  546. if( (LONG64)strucArray->Equate < 0 ){
  547. //
  548. // Negative constant
  549. //
  550. if( (LONG64)strucArray->Equate < LONG_MIN ){
  551. //
  552. // More negative than can be represented in 32 bits
  553. //
  554. sefType = SEF_EQUATE64;
  555. } else {
  556. //
  557. // Falls within [LONG_MIN..0], Leave as SEF_EQUATE32
  558. //
  559. }
  560. } else if( (ULONG64)strucArray->Equate > (ULONG_MAX) ){
  561. //
  562. // More positive than can be represented in 32 bits
  563. //
  564. sefType = SEF_EQUATE64;
  565. }
  566. //
  567. // Fall through
  568. //
  569. case SEF_EQUATE64:
  570. case SEF_COMMENT:
  571. HeaderPrint( enableMask,
  572. sefType,
  573. strucArray->Name,
  574. (UINT64)strucArray->Equate );
  575. break;
  576. case SEF_STRING:
  577. HeaderPrint( enableMask,
  578. sefType,
  579. strucArray->Name,
  580. strucArray->Equate );
  581. break;
  582. case SEF_STRUCTURE:
  583. HeaderPrint( enableMask,
  584. sefType,
  585. strucArray->Name,
  586. (ULONG)strucArray->Equate,
  587. strucArray->Name );
  588. break;
  589. case SEF_SETMASK:
  590. runningEnableMask |= strucArray->Equate;
  591. break;
  592. case SEF_CLRMASK:
  593. runningEnableMask &= ~strucArray->Equate;
  594. break;
  595. case SEF_PATH:
  596. //
  597. // Add another output file to our list.
  598. //
  599. CheckCondition( fOutputSpecified == FALSE,
  600. "setPath() in %s incompatible with -o flag\n",
  601. ObjectPath );
  602. AddNewOutputFile( strucArray->Name,
  603. (ULONG)strucArray->Flags );
  604. break;
  605. default:
  606. //
  607. // Found an SEF_TYPE we don't know about. This is fatal.
  608. //
  609. CheckCondition( FALSE,
  610. "Unknown structure type %d. "
  611. "Need an updated genxx.exe?\n",
  612. sefType );
  613. break;
  614. }
  615. } while( finished == FALSE );
  616. }
  617. VOID
  618. __cdecl
  619. CheckCondition(
  620. int Condition,
  621. const char *FormatString,
  622. ...
  623. )
  624. {
  625. va_list(arglist);
  626. va_start(arglist, FormatString);
  627. if( Condition == 0 ){
  628. //
  629. // A fatal error was encountered. Bail.
  630. //
  631. vprintf( FormatString, arglist );
  632. perror( "genxx" );
  633. exit(1);
  634. }
  635. }
  636. VOID
  637. _cdecl
  638. HeaderPrint(
  639. ULONG EnableFlags,
  640. ULONG Type,
  641. ...
  642. )
  643. {
  644. POUTPUT_FILE outputFile;
  645. char const *formatString;
  646. va_list arglist;
  647. //
  648. // Send the output to each output file as appropriate
  649. //
  650. outputFile = OutputFileList;
  651. while( outputFile != NULL ){
  652. va_start( arglist, Type );
  653. if( outputFile->EnableMask == 0 ||
  654. (outputFile->EnableMask & EnableFlags) != 0 ){
  655. //
  656. // Either this output file gets everything, or the mask
  657. // matches. Figure out which format to use... '.h' or '.inc'
  658. // style.
  659. //
  660. if( Type == SEF_STRING ){
  661. //
  662. // For SEF_STRING, strucArray->Name *is* the format string.
  663. //
  664. formatString = va_arg( arglist, PUCHAR );
  665. } else if( outputFile->IncFormat != FALSE ){
  666. //
  667. // Use the ".inc" format
  668. //
  669. formatString = Asm386FormatStringArray[ Type ];
  670. } else {
  671. //
  672. // Use the ".h" format
  673. //
  674. formatString = PreprocessedFormatStringArray[ Type ];
  675. }
  676. //
  677. // Now send it
  678. //
  679. vfprintf( outputFile->File, formatString, arglist );
  680. }
  681. va_end( arglist );
  682. //
  683. // Process all current output files.
  684. //
  685. outputFile = outputFile->Next;
  686. }
  687. }
  688. VOID
  689. GetEnvironment( VOID )
  690. {
  691. char *ntDrive;
  692. char *ntRoot;
  693. //
  694. // Set NtRoot = %_NTDRIVE%\%_NTROOT%
  695. //
  696. ntDrive = getenv( "_NTDRIVE" );
  697. ntRoot = getenv( "_NTROOT" );
  698. if( ntDrive != NULL && ntRoot != NULL ){
  699. sprintf( NtRoot, "%s%s", ntDrive, ntRoot );
  700. } else {
  701. //
  702. // If either _NTDRIVE or _NTROOT were not found in the environment,
  703. // let's try with \nt.
  704. //
  705. strcpy( NtRoot, "\\nt" );
  706. }
  707. }
  708. PSTRUC_ELEMENT
  709. FindStructureElementArray(
  710. PCHAR Buffer,
  711. ULONG BufferSize
  712. )
  713. {
  714. PCHAR searchPoint;
  715. PCHAR searchEndPoint;
  716. PSTRUC_ELEMENT strucElement;
  717. //
  718. // Search Buffer for the beginning of a structure element array.
  719. // The first element in this array contains MARKER_STRING.
  720. //
  721. searchPoint = Buffer;
  722. searchEndPoint = Buffer + BufferSize - sizeof( MarkerString );
  723. do{
  724. //
  725. // We scan the buffer a character at a time until we find a character
  726. // that matches the first character in MarkerString.
  727. //
  728. if( *searchPoint != MarkerString[ 0 ] ){
  729. continue;
  730. }
  731. //
  732. // When a matching char is found, the rest of the string is compared.
  733. //
  734. if( strcmp( searchPoint, MarkerString ) == 0 ){
  735. //
  736. // It matched too, we're done.
  737. //
  738. strucElement = CONTAINING_RECORD( searchPoint,
  739. STRUC_ELEMENT,
  740. Name );
  741. return strucElement;
  742. }
  743. } while( searchPoint++ < searchEndPoint );
  744. //
  745. // Fell out of the loop, we couldn't find the string.
  746. //
  747. return NULL;
  748. }
  749. VOID
  750. Usage( VOID ){
  751. int platformIndex;
  752. PPLATFORM platform;
  753. printf("genxx: [");
  754. platform = PlatformList;
  755. while( platform->PlatformName != NULL ){
  756. printf("-%s|", platform->PlatformName );
  757. platform++;
  758. }
  759. printf("<objpath>] [-s<h|inc>] [-o<outputpath>]\n");
  760. exit(1);
  761. }
  762. VOID
  763. ApplyFixupsToImage( VOID )
  764. {
  765. //
  766. // Applies fixups to the OBJ image loaded at ObjImage
  767. //
  768. PIMAGE_FILE_HEADER fileHeader;
  769. PIMAGE_SECTION_HEADER sectionHeader;
  770. PIMAGE_SECTION_HEADER sectionHeaderArray;
  771. PIMAGE_SYMBOL symbolTable;
  772. PIMAGE_SYMBOL symbol;
  773. PIMAGE_RELOCATION reloc;
  774. PIMAGE_RELOCATION relocArray;
  775. ULONG sectionNum;
  776. ULONG relocNum;
  777. ULONG_PTR targetVa;
  778. PULONG_PTR fixupVa;
  779. fileHeader = (PIMAGE_FILE_HEADER)ObjImage;
  780. //
  781. // We need the symbol table to apply the fixups
  782. //
  783. symbolTable = (PIMAGE_SYMBOL)(ObjImage + fileHeader->PointerToSymbolTable);
  784. //
  785. // Get a pointer to the first element in the section header
  786. //
  787. sectionHeaderArray = (PIMAGE_SECTION_HEADER)(ObjImage +
  788. sizeof( IMAGE_FILE_HEADER ) +
  789. fileHeader->SizeOfOptionalHeader);
  790. //
  791. // Apply the fixups for each section
  792. //
  793. for( sectionNum = 0;
  794. sectionNum < fileHeader->NumberOfSections;
  795. sectionNum++ ){
  796. sectionHeader = &sectionHeaderArray[ sectionNum ];
  797. if (memcmp(sectionHeader->Name, ".data", sizeof(".data")+1)) {
  798. // Not .data - don't bother with the fixup
  799. continue;
  800. }
  801. //
  802. // Apply each fixup in this section
  803. //
  804. relocArray = (PIMAGE_RELOCATION)(ObjImage +
  805. sectionHeader->PointerToRelocations);
  806. for( relocNum = 0;
  807. relocNum < sectionHeader->NumberOfRelocations;
  808. relocNum++ ){
  809. reloc = &relocArray[ relocNum ];
  810. //
  811. // The relocation gives us the position in the image of the
  812. // relocation modification (VirtualAddress). To find out what
  813. // to put there, we have to look the symbol up in the symbol index.
  814. //
  815. symbol = &symbolTable[ reloc->SymbolTableIndex ];
  816. targetVa =
  817. sectionHeaderArray[ symbol->SectionNumber-1 ].PointerToRawData;
  818. targetVa += symbol->Value;
  819. targetVa += (ULONG_PTR)ObjImage;
  820. fixupVa = (PULONG_PTR)(ObjImage +
  821. reloc->VirtualAddress +
  822. sectionHeader->PointerToRawData );
  823. *fixupVa = targetVa;
  824. }
  825. }
  826. }
  827. BOOLEAN
  828. IsWhiteSpace(
  829. CHAR Char
  830. )
  831. {
  832. if( Char == '\t' ||
  833. Char == ' ' ||
  834. Char == '\r' ||
  835. Char == '\n' ){
  836. return TRUE;
  837. } else {
  838. return FALSE;
  839. }
  840. }
  841. PCHAR
  842. StripWhiteSpace(
  843. PCHAR String
  844. )
  845. {
  846. PCHAR chr;
  847. ULONG strLen;
  848. strLen = strlen( String );
  849. if( strLen == 0 ){
  850. return String;
  851. }
  852. //
  853. // Strip off trailing whitespace
  854. //
  855. chr = String + strLen - 1;
  856. while( IsWhiteSpace( *chr )){
  857. *chr = '\0';
  858. chr--;
  859. }
  860. //
  861. // Advance past leading whitespace
  862. //
  863. chr = String;
  864. while( IsWhiteSpace( *chr )){
  865. chr++;
  866. }
  867. return chr;
  868. }