Leaked source code of windows server 2003
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.

1160 lines
27 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. strncpy( HeaderPath, arg+1, sizeof(HeaderPath) - 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. strncpy( KernelHeaderPath, arg+1, sizeof(KernelHeaderPath) - 1 );
  259. validSwitch = TRUE;
  260. break;
  261. case 'h':
  262. //
  263. // Hal header path. Save off.
  264. //
  265. fHalHeaderPath = TRUE;
  266. strncpy( HalHeaderPath, arg+1, sizeof(HalHeaderPath) - 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. _snprintf( ObjectPath,
  282. sizeof(ObjectPath) - 1,
  283. "%s\\%s",
  284. NtRoot,
  285. platform->ObjPath );
  286. //
  287. // Add the header paths too.
  288. //
  289. headerPath = platform->HeaderPathList;
  290. while( headerPath->HeaderPath != NULL ){
  291. if (fHalHeaderPath && (headerPath->Flags & SEF_HAL)) {
  292. strncpy(TempBuf, HalHeaderPath, sizeof(TempBuf) - 1);
  293. AddNewAbsoluteOutputFile( HalHeaderPath, headerPath->Flags );
  294. } else
  295. if (fKernelHeaderPath && (headerPath->Flags & SEF_KERNEL)) {
  296. strncpy(TempBuf, KernelHeaderPath, sizeof(TempBuf) - 1);
  297. AddNewAbsoluteOutputFile( KernelHeaderPath, headerPath->Flags );
  298. } else {
  299. AddNewOutputFile( headerPath->HeaderPath,
  300. headerPath->Flags );
  301. }
  302. headerPath++;
  303. }
  304. validSwitch = TRUE;
  305. break;
  306. }
  307. platform++;
  308. }
  309. break;
  310. }
  311. if( validSwitch == FALSE ){
  312. Usage();
  313. }
  314. } else {
  315. //
  316. // We are dealing with something that is not a switch. The only
  317. // possibility is the path to the object file.
  318. //
  319. strncpy( ObjectPath, arg, sizeof(ObjectPath) - 1 );
  320. }
  321. }
  322. CheckCondition( ObjectPath[0] != '\0',
  323. "Object path not specified\n" );
  324. if( fOutputSpecified != FALSE ){
  325. //
  326. // The output path was specified
  327. //
  328. AddNewAbsoluteOutputFile( HeaderPath,
  329. fIncFormat ? SEF_INC_FORMAT : SEF_H_FORMAT );
  330. }
  331. strucArray = LoadObjImage( ObjectPath );
  332. BuildHeaderFiles( strucArray );
  333. CloseOutputFiles();
  334. //
  335. // Indicate success.
  336. //
  337. return 0;
  338. }
  339. VOID
  340. AddNewAbsoluteOutputFile(
  341. PUCHAR AbsolutePath,
  342. ULONG Flags
  343. )
  344. {
  345. POUTPUT_FILE outputFile;
  346. outputFile = malloc( sizeof( OUTPUT_FILE ));
  347. CheckCondition( outputFile != NULL, "Out of memory\n" );
  348. outputFile->EnableMask = (ULONG)(Flags & SEF_ENABLE_MASK);
  349. if( (Flags & SEF_INC_FORMAT_MASK) == SEF_INC_FORMAT ){
  350. //
  351. // This file will be created in '.inc' format for the 386 assembler.
  352. //
  353. outputFile->IncFormat = TRUE;
  354. } else {
  355. //
  356. // This file will be created in '.h' format for the standard C
  357. // preprocessor.
  358. //
  359. outputFile->IncFormat = FALSE;
  360. }
  361. outputFile->File = fopen( AbsolutePath, "w" );
  362. CheckCondition( outputFile->File != NULL,
  363. "Cannot open %s for writing.\n",
  364. TempBuf );
  365. printf("%s -> %s\n", ObjectPath, TempBuf );
  366. //
  367. // Link this structure into the list of output files
  368. //
  369. outputFile->Next = OutputFileList;
  370. OutputFileList = outputFile;
  371. }
  372. VOID
  373. AddNewOutputFile(
  374. PUCHAR RootRelativePath,
  375. ULONG Flags
  376. )
  377. {
  378. //
  379. // Create the canonoical file path and open the file.
  380. //
  381. _snprintf( TempBuf,
  382. sizeof(TempBuf) - 1,
  383. "%s\\%s",
  384. NtRoot,
  385. RootRelativePath );
  386. AddNewAbsoluteOutputFile( TempBuf, Flags );
  387. }
  388. VOID
  389. CloseOutputFiles( VOID )
  390. {
  391. POUTPUT_FILE outputFile;
  392. outputFile = OutputFileList;
  393. while( outputFile != NULL ){
  394. fclose( outputFile->File );
  395. outputFile = outputFile->Next;
  396. }
  397. }
  398. PSTRUC_ELEMENT
  399. LoadObjImage(
  400. PUCHAR ImagePath
  401. )
  402. {
  403. long objImageSize;
  404. int result;
  405. PSTRUC_ELEMENT strucArray;
  406. FILE * objFile;
  407. //
  408. // Open up and read the platform-specific .obj file.
  409. //
  410. objFile = fopen( ImagePath, "rb" );
  411. CheckCondition( objFile != NULL,
  412. "Cannot open %s for reading.\n"
  413. "This file must have been created by the compiler for the "
  414. "target platform.\n",
  415. ImagePath );
  416. //
  417. // Get the file size, allocate a buffer, read it in, and close.
  418. //
  419. result = fseek( objFile, 0, SEEK_END );
  420. CheckCondition( result == 0,
  421. "fseek() failed, error %d\n",
  422. errno );
  423. objImageSize = ftell( objFile );
  424. CheckCondition( objImageSize != -1L,
  425. "ftell() failed, error %d\n",
  426. errno );
  427. CheckCondition( objImageSize > 0,
  428. "%s appears to be corrupt\n",
  429. ImagePath );
  430. ObjImage = malloc( objImageSize );
  431. CheckCondition( ObjImage != NULL,
  432. "Out of memory\n" );
  433. result = fseek( objFile, 0, SEEK_SET );
  434. CheckCondition( result == 0,
  435. "fseek() failed, error %d\n",
  436. errno );
  437. result = fread( ObjImage, 1, objImageSize, objFile );
  438. CheckCondition( result == objImageSize,
  439. "Error reading from %s\n",
  440. ImagePath );
  441. fclose( objFile );
  442. //
  443. // Even though this is just an .obj file, we want it "fixed up"
  444. //
  445. ApplyFixupsToImage();
  446. //
  447. // Got the image, find the beginning of the array.
  448. //
  449. strucArray = FindStructureElementArray( ObjImage,
  450. objImageSize );
  451. CheckCondition( strucArray != NULL,
  452. "%s does not contain a structure description array.\n",
  453. ImagePath );
  454. return strucArray;
  455. }
  456. VOID
  457. BuildHeaderFiles(
  458. STRUC_ELEMENT UNALIGNED *StrucArray
  459. )
  460. {
  461. STRUC_ELEMENT UNALIGNED *strucArray;
  462. ULONG runningEnableMask;
  463. ULONG enableMask;
  464. ULONG sefType;
  465. const char *formatString;
  466. ULONG bitFieldStart;
  467. PUINT64 bitFieldPtr;
  468. UINT64 bitFieldData;
  469. PCHAR name;
  470. BOOLEAN finished;
  471. //
  472. // Process each element in the array. The first element is the
  473. // marker string element, so it is skipped.
  474. //
  475. runningEnableMask = 0;
  476. finished = FALSE;
  477. strucArray = StrucArray;
  478. do{
  479. strucArray++;
  480. sefType = (ULONG)(strucArray->Flags & SEF_TYPE_MASK);
  481. if( sefType == SEF_BITFLD ){
  482. //
  483. // For bitfields, the enable mask is set explicitly
  484. //
  485. enableMask = (ULONG)(strucArray->Flags & SEF_ENABLE_MASK);
  486. } else {
  487. //
  488. // For everything else, we use the current runningEnableMask
  489. //
  490. enableMask = runningEnableMask;
  491. }
  492. switch( sefType ){
  493. case SEF_BITFLD:
  494. //
  495. // This kind of element is tricky. "Equate" is actually a
  496. // pointer to a bitfield structure. This structure has had
  497. // a portion of it (the bitfield) initialized to ones.
  498. //
  499. // It is the job of this case to poke around in that
  500. // structure in order to determine where the bitfield landed.
  501. //
  502. bitFieldPtr = (PINT64)(strucArray->Equate);
  503. bitFieldData = *bitFieldPtr;
  504. //
  505. // Determine the zero-based starting bitnumber of the field.
  506. //
  507. bitFieldStart = 0;
  508. while( (bitFieldData & ((UINT64)1 << bitFieldStart)) == 0 ){
  509. bitFieldStart++;
  510. }
  511. name = StripWhiteSpace( strucArray->Name );
  512. if( *name != '\0'){
  513. HeaderPrint( enableMask,
  514. sefType,
  515. name,
  516. bitFieldData,
  517. name,
  518. bitFieldStart );
  519. }
  520. //
  521. // A bitfield can be followed by any number of
  522. // SEF_BITALIAS entries. These are alias names for the
  523. // bitmask that was just defined.
  524. //
  525. while( TRUE ){
  526. sefType = (ULONG)((strucArray+1)->Flags & SEF_TYPE_MASK);
  527. if( sefType != SEF_BITALIAS ){
  528. //
  529. // No more aliases.
  530. //
  531. break;
  532. }
  533. //
  534. // This is a bitmask alias field, process it.
  535. //
  536. strucArray++;
  537. name = StripWhiteSpace( strucArray->Name );
  538. HeaderPrint( enableMask,
  539. sefType,
  540. name,
  541. bitFieldData );
  542. }
  543. break;
  544. case SEF_END:
  545. finished = TRUE;
  546. break;
  547. case SEF_EQUATE:
  548. if( (LONG64)strucArray->Equate < 0 ){
  549. //
  550. // Negative constant
  551. //
  552. if( (LONG64)strucArray->Equate < LONG_MIN ){
  553. //
  554. // More negative than can be represented in 32 bits
  555. //
  556. sefType = SEF_EQUATE64;
  557. } else {
  558. //
  559. // Falls within [LONG_MIN..0], Leave as SEF_EQUATE32
  560. //
  561. }
  562. } else if( (ULONG64)strucArray->Equate > (ULONG_MAX) ){
  563. //
  564. // More positive than can be represented in 32 bits
  565. //
  566. sefType = SEF_EQUATE64;
  567. }
  568. //
  569. // Fall through
  570. //
  571. case SEF_EQUATE64:
  572. case SEF_COMMENT:
  573. HeaderPrint( enableMask,
  574. sefType,
  575. strucArray->Name,
  576. (UINT64)strucArray->Equate );
  577. break;
  578. case SEF_STRING:
  579. HeaderPrint( enableMask,
  580. sefType,
  581. strucArray->Name,
  582. strucArray->Equate );
  583. break;
  584. case SEF_STRUCTURE:
  585. HeaderPrint( enableMask,
  586. sefType,
  587. strucArray->Name,
  588. (ULONG)strucArray->Equate,
  589. strucArray->Name );
  590. break;
  591. case SEF_SETMASK:
  592. runningEnableMask |= strucArray->Equate;
  593. break;
  594. case SEF_CLRMASK:
  595. runningEnableMask &= ~strucArray->Equate;
  596. break;
  597. case SEF_PATH:
  598. //
  599. // Add another output file to our list.
  600. //
  601. CheckCondition( fOutputSpecified == FALSE,
  602. "setPath() in %s incompatible with -o flag\n",
  603. ObjectPath );
  604. AddNewOutputFile( strucArray->Name,
  605. (ULONG)strucArray->Flags );
  606. break;
  607. default:
  608. //
  609. // Found an SEF_TYPE we don't know about. This is fatal.
  610. //
  611. CheckCondition( FALSE,
  612. "Unknown structure type %d. "
  613. "Need an updated genxx.exe?\n",
  614. sefType );
  615. break;
  616. }
  617. } while( finished == FALSE );
  618. }
  619. VOID
  620. __cdecl
  621. CheckCondition(
  622. int Condition,
  623. const char *FormatString,
  624. ...
  625. )
  626. {
  627. va_list(arglist);
  628. va_start(arglist, FormatString);
  629. if( Condition == 0 ){
  630. //
  631. // A fatal error was encountered. Bail.
  632. //
  633. vprintf( FormatString, arglist );
  634. perror( "genxx" );
  635. exit(1);
  636. }
  637. }
  638. VOID
  639. _cdecl
  640. HeaderPrint(
  641. ULONG EnableFlags,
  642. ULONG Type,
  643. ...
  644. )
  645. {
  646. POUTPUT_FILE outputFile;
  647. char const *formatString;
  648. va_list arglist;
  649. //
  650. // Send the output to each output file as appropriate
  651. //
  652. outputFile = OutputFileList;
  653. while( outputFile != NULL ){
  654. va_start( arglist, Type );
  655. if( outputFile->EnableMask == 0 ||
  656. (outputFile->EnableMask & EnableFlags) != 0 ){
  657. //
  658. // Either this output file gets everything, or the mask
  659. // matches. Figure out which format to use... '.h' or '.inc'
  660. // style.
  661. //
  662. if( Type == SEF_STRING ){
  663. //
  664. // For SEF_STRING, strucArray->Name *is* the format string.
  665. //
  666. formatString = va_arg( arglist, PUCHAR );
  667. } else if( outputFile->IncFormat != FALSE ){
  668. //
  669. // Use the ".inc" format
  670. //
  671. formatString = Asm386FormatStringArray[ Type ];
  672. } else {
  673. //
  674. // Use the ".h" format
  675. //
  676. formatString = PreprocessedFormatStringArray[ Type ];
  677. }
  678. //
  679. // Now send it
  680. //
  681. vfprintf( outputFile->File, formatString, arglist );
  682. }
  683. va_end( arglist );
  684. //
  685. // Process all current output files.
  686. //
  687. outputFile = outputFile->Next;
  688. }
  689. }
  690. VOID
  691. GetEnvironment( VOID )
  692. {
  693. char *ntDrive;
  694. char *ntRoot;
  695. //
  696. // Set NtRoot = %_NTDRIVE%\%_NTROOT%
  697. //
  698. ntDrive = getenv( "_NTDRIVE" );
  699. ntRoot = getenv( "_NTROOT" );
  700. if( ntDrive != NULL && ntRoot != NULL ){
  701. _snprintf( NtRoot, sizeof(NtRoot) - 1, "%s%s", ntDrive, ntRoot );
  702. } else {
  703. //
  704. // If either _NTDRIVE or _NTROOT were not found in the environment,
  705. // let's try with \nt.
  706. //
  707. strncpy( NtRoot, "\\nt", sizeof(NtRoot) - 1 );
  708. }
  709. }
  710. PSTRUC_ELEMENT
  711. FindStructureElementArray(
  712. PCHAR Buffer,
  713. ULONG BufferSize
  714. )
  715. {
  716. PCHAR searchPoint;
  717. PCHAR searchEndPoint;
  718. PSTRUC_ELEMENT strucElement;
  719. //
  720. // Search Buffer for the beginning of a structure element array.
  721. // The first element in this array contains MARKER_STRING.
  722. //
  723. searchPoint = Buffer;
  724. searchEndPoint = Buffer + BufferSize - sizeof( MarkerString );
  725. do{
  726. //
  727. // We scan the buffer a character at a time until we find a character
  728. // that matches the first character in MarkerString.
  729. //
  730. if( *searchPoint != MarkerString[ 0 ] ){
  731. continue;
  732. }
  733. //
  734. // When a matching char is found, the rest of the string is compared.
  735. //
  736. if( strcmp( searchPoint, MarkerString ) == 0 ){
  737. //
  738. // It matched too, we're done.
  739. //
  740. strucElement = CONTAINING_RECORD( searchPoint,
  741. STRUC_ELEMENT,
  742. Name );
  743. return strucElement;
  744. }
  745. } while( searchPoint++ < searchEndPoint );
  746. //
  747. // Fell out of the loop, we couldn't find the string.
  748. //
  749. return NULL;
  750. }
  751. VOID
  752. Usage( VOID ){
  753. int platformIndex;
  754. PPLATFORM platform;
  755. printf("genxx: [");
  756. platform = PlatformList;
  757. while( platform->PlatformName != NULL ){
  758. printf("-%s|", platform->PlatformName );
  759. platform++;
  760. }
  761. printf("<objpath>] [-s<h|inc>] [-o<outputpath>]\n");
  762. exit(1);
  763. }
  764. VOID
  765. ApplyFixupsToImage( VOID )
  766. {
  767. //
  768. // Applies fixups to the OBJ image loaded at ObjImage
  769. //
  770. PIMAGE_FILE_HEADER fileHeader;
  771. PIMAGE_SECTION_HEADER sectionHeader;
  772. PIMAGE_SECTION_HEADER sectionHeaderArray;
  773. PIMAGE_SYMBOL symbolTable;
  774. PIMAGE_SYMBOL symbol;
  775. PIMAGE_RELOCATION reloc;
  776. PIMAGE_RELOCATION relocArray;
  777. ULONG sectionNum;
  778. ULONG relocNum;
  779. ULONG_PTR targetVa;
  780. PULONG_PTR fixupVa;
  781. fileHeader = (PIMAGE_FILE_HEADER)ObjImage;
  782. //
  783. // We need the symbol table to apply the fixups
  784. //
  785. symbolTable = (PIMAGE_SYMBOL)(ObjImage + fileHeader->PointerToSymbolTable);
  786. //
  787. // Get a pointer to the first element in the section header
  788. //
  789. sectionHeaderArray = (PIMAGE_SECTION_HEADER)(ObjImage +
  790. sizeof( IMAGE_FILE_HEADER ) +
  791. fileHeader->SizeOfOptionalHeader);
  792. //
  793. // Apply the fixups for each section
  794. //
  795. for( sectionNum = 0;
  796. sectionNum < fileHeader->NumberOfSections;
  797. sectionNum++ ){
  798. sectionHeader = &sectionHeaderArray[ sectionNum ];
  799. if (memcmp(sectionHeader->Name, ".data", sizeof(".data")+1)) {
  800. // Not .data - don't bother with the fixup
  801. continue;
  802. }
  803. //
  804. // Apply each fixup in this section
  805. //
  806. relocArray = (PIMAGE_RELOCATION)(ObjImage +
  807. sectionHeader->PointerToRelocations);
  808. for( relocNum = 0;
  809. relocNum < sectionHeader->NumberOfRelocations;
  810. relocNum++ ){
  811. reloc = &relocArray[ relocNum ];
  812. //
  813. // The relocation gives us the position in the image of the
  814. // relocation modification (VirtualAddress). To find out what
  815. // to put there, we have to look the symbol up in the symbol index.
  816. //
  817. symbol = &symbolTable[ reloc->SymbolTableIndex ];
  818. targetVa =
  819. sectionHeaderArray[ symbol->SectionNumber-1 ].PointerToRawData;
  820. targetVa += symbol->Value;
  821. targetVa += (ULONG_PTR)ObjImage;
  822. fixupVa = (PULONG_PTR)(ObjImage +
  823. reloc->VirtualAddress +
  824. sectionHeader->PointerToRawData );
  825. *fixupVa = targetVa;
  826. }
  827. }
  828. }
  829. BOOLEAN
  830. IsWhiteSpace(
  831. CHAR Char
  832. )
  833. {
  834. if( Char == '\t' ||
  835. Char == ' ' ||
  836. Char == '\r' ||
  837. Char == '\n' ){
  838. return TRUE;
  839. } else {
  840. return FALSE;
  841. }
  842. }
  843. PCHAR
  844. StripWhiteSpace(
  845. PCHAR String
  846. )
  847. {
  848. PCHAR chr;
  849. ULONG strLen;
  850. strLen = strlen( String );
  851. if( strLen == 0 ){
  852. return String;
  853. }
  854. //
  855. // Strip off trailing whitespace
  856. //
  857. chr = String + strLen - 1;
  858. while( IsWhiteSpace( *chr )){
  859. *chr = '\0';
  860. chr--;
  861. }
  862. //
  863. // Advance past leading whitespace
  864. //
  865. chr = String;
  866. while( IsWhiteSpace( *chr )){
  867. chr++;
  868. }
  869. return chr;
  870. }