|
|
1.1 ! root 1: /*++ ! 2: ! 3: ! 4: Copyright (c) 1992 Microsoft Corporation ! 5: ! 6: Module Name: ! 7: ! 8: symedit.c ! 9: ! 10: Abstract: ! 11: ! 12: ! 13: Author: ! 14: ! 15: Wesley A. Witt (wesw) 19-April-1993 ! 16: ! 17: Environment: ! 18: ! 19: Win32, User Mode ! 20: ! 21: --*/ ! 22: ! 23: #include <windows.h> ! 24: #include <stdlib.h> ! 25: #include <stdio.h> ! 26: #include <string.h> ! 27: ! 28: #include "symcvt.h" ! 29: #include "cv.h" ! 30: #include "cofftocv.h" ! 31: #include "symtocv.h" ! 32: #include "strings.h" ! 33: ! 34: #include <imagehlp.h> ! 35: ! 36: ! 37: /* ! 38: * prototypes for this module ! 39: */ ! 40: ! 41: BOOL CalculateOutputFilePointers( PIMAGEPOINTERS pi, PIMAGEPOINTERS po ); ! 42: void ProcessCommandLineArgs( int argc, char *argv[] ); ! 43: void PrintCopyright( void ); ! 44: void PrintUsage( void ); ! 45: void FatalError( int, ... ); ! 46: BOOL MapOutputFile ( PPOINTERS p, char *fname, int ); ! 47: void ComputeChecksum( char *szExeFile ); ! 48: void ReadDebugInfo( PPOINTERS p ); ! 49: void WriteDebugInfo( PPOINTERS p, BOOL, BOOL ); ! 50: void MungeDebugHeadersCoffToCv( PPOINTERS p, BOOL fAddCV ); ! 51: void MungeExeName( PPOINTERS p, char * szExeName ); ! 52: void DoCoffToCv(char *, char *, BOOL); ! 53: void DoSymToCv(char *, char *, char *, char *); ! 54: void DoNameChange(char *, char *, char *); ! 55: void DoExtract(char *, char *, char *); ! 56: void DoStrip(char *, char *); ! 57: ! 58: IMAGE_DEBUG_DIRECTORY DbgDirSpare; ! 59: IMAGE_DEBUG_DIRECTORY DbgDirCoff; ! 60: ! 61: #define AdjustPtr(ptr) (((ptr) != NULL) ? ((DWORD)ptr - (DWORD)pi->fptr + (DWORD)po->fptr) : ((DWORD)(ptr))) ! 62: ! 63: ! 64: ! 65: int _CRTAPI1 ! 66: main( ! 67: int argc, ! 68: char * argv[] ! 69: ) ! 70: /*++ ! 71: ! 72: Routine Description: ! 73: ! 74: Shell for this utility. ! 75: ! 76: Arguments: ! 77: ! 78: argc - argument count ! 79: argv - argument pointers ! 80: ! 81: ! 82: Return Value: ! 83: ! 84: 0 - image was converted ! 85: >0 - image could not be converted ! 86: ! 87: --*/ ! 88: ! 89: { ! 90: /* ! 91: * Scan the command line and check what operations we are doing ! 92: */ ! 93: ! 94: ProcessCommandLineArgs( argc, argv ); ! 95: return 0; ! 96: } ! 97: ! 98: void ! 99: PrintCopyright( void ) ! 100: ! 101: /*++ ! 102: ! 103: Routine Description: ! 104: ! 105: Prints the MS copyright message to stdout. ! 106: ! 107: Arguments: ! 108: ! 109: void ! 110: ! 111: ! 112: Return Value: ! 113: ! 114: void ! 115: ! 116: --*/ ! 117: ! 118: { ! 119: printf( "\nMicrosoft(R) Windows NT SymEdit Version 1.0\n" ); ! 120: printf( "(C) 1989-1993 Microsoft Corp. All rights reserved.\n\n"); ! 121: } ! 122: ! 123: void ! 124: PrintUsage( void ) ! 125: ! 126: /*++ ! 127: ! 128: Routine Description: ! 129: ! 130: Prints the command line help to stdout ! 131: ! 132: Arguments: ! 133: ! 134: void ! 135: ! 136: ! 137: Return Value: ! 138: ! 139: void ! 140: ! 141: --*/ ! 142: ! 143: { ! 144: PrintCopyright(); ! 145: printf("\nUsage: SYMEDIT <OPERATION> -q -o<file out> <file in>\n\n" ); ! 146: printf("\t<OPERATION> is:\n"); ! 147: printf("\tA\tAdd debug information\n"); ! 148: printf("\tC\tConvert symbol information\n" ); ! 149: printf("\tN\tEdit name field\n"); ! 150: printf("\tX\tExtract debug information\n"); ! 151: printf("\tS\tStrip all debug information\n\n"); ! 152: printf("Options:\n"); ! 153: printf("\t-a\t\tAdd CodeView debug info to file\n"); ! 154: printf("\t-n<name>\tName to change to\n"); ! 155: printf("\t-o<file>\tspecify output file\n" ); ! 156: printf("\t-q\t\tquiet mode\n" ); ! 157: printf("\t-s<file>\tSym file source\n"); ! 158: } ! 159: ! 160: void ! 161: ProcessCommandLineArgs( int argc, char *argv[] ) ! 162: ! 163: /*++ ! 164: ! 165: Routine Description: ! 166: ! 167: Processes the command line arguments and sets global flags to ! 168: indicate the user's desired behavior. ! 169: ! 170: Arguments: ! 171: ! 172: argc - argument count ! 173: argv - argument pointers ! 174: ! 175: ! 176: Return Value: ! 177: ! 178: void ! 179: ! 180: --*/ ! 181: ! 182: { ! 183: int i; ! 184: BOOL fQuiet = FALSE; ! 185: BOOL fSilent = FALSE; ! 186: char * szOutputFile = NULL; ! 187: char * szInputFile = NULL; ! 188: char * szExeName = NULL; ! 189: char * szDbgFile = NULL; ! 190: char * szSymFile = NULL; ! 191: int iOperation; ! 192: BOOLEAN fAddCV = FALSE; ! 193: ! 194: /* ! 195: * Minimun number of of arguments is 2 -- program and operation ! 196: */ ! 197: ! 198: if (argc < 2) { ! 199: PrintUsage(); ! 200: exit(1); ! 201: } ! 202: ! 203: if ((strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "?") == 0)) { ! 204: PrintUsage(); ! 205: exit(1); ! 206: } ! 207: ! 208: /* ! 209: * All operations on 1 character wide ! 210: */ ! 211: ! 212: if (argv[1][1] != 0) { ! 213: FatalError(ERR_OP_UNKNOWN, argv[1]); ! 214: } ! 215: ! 216: /* ! 217: * Validate the operation ! 218: */ ! 219: ! 220: switch( argv[1][0] ) { ! 221: case 'C': ! 222: case 'N': ! 223: case 'X': ! 224: case 'S': ! 225: iOperation = argv[1][0]; ! 226: break; ! 227: default: ! 228: FatalError(ERR_OP_UNKNOWN, argv[1]); ! 229: } ! 230: ! 231: /* ! 232: * Parse out any other switches on the command line ! 233: */ ! 234: ! 235: for (i=2; i<argc; i++) { ! 236: if ((argv[i][0] == '-') || (argv[i][0] == '/')) { ! 237: switch (argv[i][1]) { ! 238: /* ! 239: * Add the CV debug information section rather than ! 240: * replace the COFF section with the CV info. ! 241: */ ! 242: case 'a': ! 243: case 'A': ! 244: fAddCV = TRUE; ! 245: break; ! 246: ! 247: /* ! 248: * Specify the output name for the DBG file ! 249: */ ! 250: ! 251: case 'd': ! 252: case 'D': ! 253: if (argv[i][2] == 0) { ! 254: i += 1; ! 255: szDbgFile = argv[i]; ! 256: } else { ! 257: szDbgFile = &argv[i][2]; ! 258: } ! 259: break; ! 260: ! 261: /* ! 262: * Specify a new name to shove into the name of the ! 263: * debuggee field in the Misc. Debug info field ! 264: */ ! 265: ! 266: case 'N': ! 267: case 'n': ! 268: if (argv[i][2] == 0) { ! 269: i += 1; ! 270: szExeName = argv[i]; ! 271: } else { ! 272: szExeName = &argv[i][2]; ! 273: } ! 274: break; ! 275: ! 276: /* ! 277: * Specify the name of the output file ! 278: */ ! 279: ! 280: case 'O': ! 281: case 'o': ! 282: if (argv[i][2] == 0) { ! 283: i += 1; ! 284: szOutputFile = argv[i]; ! 285: } else { ! 286: szOutputFile = &argv[i][2]; ! 287: } ! 288: break; ! 289: ! 290: /* ! 291: * Be quite and don't put out the banner ! 292: */ ! 293: ! 294: case 'Q': ! 295: case 'q': ! 296: fQuiet = TRUE; ! 297: fSilent = TRUE; ! 298: break; ! 299: ! 300: /* ! 301: * Replace COFF debug information with CODEVIEW debug information ! 302: */ ! 303: ! 304: case 'R': ! 305: case 'r': ! 306: break; ! 307: ! 308: /* ! 309: * Convert a Symbol File to CV info ! 310: */ ! 311: ! 312: case 'S': ! 313: case 's': ! 314: if (argv[i][2] == 0) { ! 315: i += 1; ! 316: szSymFile = argv[i]; ! 317: } else { ! 318: szSymFile = &argv[i][2]; ! 319: } ! 320: break; ! 321: ! 322: /* ! 323: * Print the command line options ! 324: */ ! 325: ! 326: case '?': ! 327: PrintUsage(); ! 328: exit(1); ! 329: break; ! 330: ! 331: /* ! 332: * Unrecognized option ! 333: */ ! 334: ! 335: default: ! 336: FatalError( ERR_OP_UNKNOWN, argv[i] ); ! 337: break; ! 338: } ! 339: } else { ! 340: /* ! 341: * No leading switch character -- must be a file name ! 342: */ ! 343: ! 344: szInputFile = &argv[i][0]; ! 345: ! 346: /* ! 347: * Process the file(s) ! 348: */ ! 349: ! 350: if (!fQuiet) { ! 351: PrintCopyright(); ! 352: fQuiet = TRUE; ! 353: } ! 354: ! 355: if (!fSilent) { ! 356: printf("processing file: %s\n", szInputFile ); ! 357: } ! 358: ! 359: /* ! 360: * Do switch validation cheching and setup any missing global variables ! 361: */ ! 362: ! 363: switch ( iOperation ) { ! 364: /* ! 365: * Add debug information to an exe file ! 366: * ! 367: * Must specify in input file ! 368: * Optional outputfile ! 369: * Must specify a debug info file ! 370: */ ! 371: ! 372: case 'A': ! 373: break; ! 374: ! 375: /* ! 376: * For conversions -- there are three types ! 377: * ! 378: * 1. Coff to CV -- add ! 379: * 2. Coff to CV -- replace ! 380: * 3. SYM to CV --- add ! 381: * 4. SYM to CV -- seperate file ! 382: * ! 383: * Optional input file (not needed for case 4) ! 384: * Optional output file ! 385: * Optional sym file (implys sym->CV) ! 386: * Optional DBG file ! 387: */ ! 388: ! 389: case 'C': ! 390: if (szSymFile == NULL) { ! 391: DoCoffToCv(szInputFile, szOutputFile, fAddCV); ! 392: } else { ! 393: DoSymToCv(szInputFile, szOutputFile, szDbgFile, szSymFile); ! 394: } ! 395: szInputFile = NULL; ! 396: szOutputFile = NULL; ! 397: szDbgFile = NULL; ! 398: szSymFile = NULL; ! 399: break; ! 400: ! 401: /* ! 402: * For changing the name of the debuggee -- ! 403: * Must specify input file ! 404: * Must specify new name ! 405: * Optional output file ! 406: */ ! 407: ! 408: case 'N': ! 409: DoNameChange(szInputFile, szOutputFile, szExeName); ! 410: szInputFile = NULL; ! 411: szOutputFile = NULL; ! 412: szExeName = NULL; ! 413: break; ! 414: ! 415: /* ! 416: * For extraction of debug information ! 417: * Must specify input file ! 418: * Optional output file name ! 419: * Optional debug file name ! 420: */ ! 421: ! 422: case 'X': ! 423: DoExtract(szInputFile, szOutputFile, szDbgFile); ! 424: break; ! 425: ! 426: /* ! 427: * For full strip of debug information ! 428: * Must specify input file ! 429: * Optional output file ! 430: * Optional debug file name ! 431: */ ! 432: ! 433: case 'S': ! 434: DoStrip(szInputFile, szOutputFile); ! 435: break; ! 436: } ! 437: } ! 438: } ! 439: return; ! 440: } /* ProcessCommandLineArgs() */ ! 441: ! 442: ! 443: void ! 444: ReadDebugInfo( ! 445: PPOINTERS p ! 446: ) ! 447: /*++ ! 448: ! 449: Routine Description: ! 450: ! 451: This function will go out and read in all of the debug information ! 452: into memory -- this is required because the input and output ! 453: files might be the same, if so then writing out informaiton may ! 454: destory data we need at a later time. ! 455: ! 456: Arguments: ! 457: ! 458: p - Supplies a pointer to the structure describing the debug info file ! 459: ! 460: Return Value: ! 461: ! 462: None. ! 463: ! 464: --*/ ! 465: ! 466: { ! 467: int i; ! 468: int cb; ! 469: char * pb; ! 470: PIMAGE_COFF_SYMBOLS_HEADER pCoffDbgInfo; ! 471: ! 472: ! 473: /* ! 474: * Allocate space to save pointers to debug info ! 475: */ ! 476: ! 477: p->iptrs.rgpbDebugSave = (PCHAR *) malloc(p->iptrs.cDebugDir * sizeof(PCHAR)); ! 478: memset(p->iptrs.rgpbDebugSave, 0, p->iptrs.cDebugDir * sizeof(PCHAR)); ! 479: ! 480: /* ! 481: * Check each possible debug type record ! 482: */ ! 483: ! 484: for (i=0; i<p->iptrs.cDebugDir; i++) { ! 485: /* ! 486: * If there was debug information then copy over the ! 487: * description block and cache in the actual debug ! 488: * data. ! 489: */ ! 490: ! 491: if ((i != IMAGE_DEBUG_TYPE_COFF) && (p->iptrs.rgDebugDir[i] != NULL)) { ! 492: p->iptrs.rgpbDebugSave[i] = ! 493: malloc( p->iptrs.rgDebugDir[i]->SizeOfData ); ! 494: if (p->iptrs.rgpbDebugSave[i] == NULL) { ! 495: FatalError(ERR_NO_MEMORY); ! 496: } ! 497: _try { ! 498: memcpy(p->iptrs.rgpbDebugSave[i], ! 499: p->iptrs.fptr + ! 500: p->iptrs.rgDebugDir[i]->PointerToRawData, ! 501: p->iptrs.rgDebugDir[i]->SizeOfData ); ! 502: } _except(EXCEPTION_EXECUTE_HANDLER ) { ! 503: free(p->iptrs.rgpbDebugSave[i]); ! 504: p->iptrs.rgpbDebugSave[i] = NULL; ! 505: } ! 506: } ! 507: } ! 508: ! 509: /* ! 510: * Treat COFF debug information seperately -- since the linker loves ! 511: * to mix it in with other things ! 512: */ ! 513: ! 514: if (p->iptrs.rgDebugDir[IMAGE_DEBUG_TYPE_COFF] != NULL) { ! 515: DbgDirCoff = *COFF_DIR(&p->iptrs); ! 516: ! 517: /* ! 518: * Allocate space to save the coff debug info ! 519: */ ! 520: ! 521: pb = p->iptrs.rgpbDebugSave[i] = malloc(DbgDirCoff.SizeOfData); ! 522: ! 523: /* ! 524: * Copy over and point to the description for the ! 525: * debug info. ! 526: */ ! 527: ! 528: memcpy(pb, DbgDirCoff.PointerToRawData + p->iptrs.fptr, ! 529: sizeof(IMAGE_COFF_SYMBOLS_HEADER)); ! 530: pCoffDbgInfo = (PIMAGE_COFF_SYMBOLS_HEADER) pb; ! 531: ! 532: /* ! 533: * Now figure out how much space we really have -- only things ! 534: * after the first symbol are "good" -- everything else is ! 535: * suspect as part of something else. ! 536: */ ! 537: ! 538: cb = DbgDirCoff.SizeOfData - pCoffDbgInfo->LvaToFirstSymbol; ! 539: ! 540: /* ! 541: * Now copy over the real symbol information and set up the ! 542: * new pointers in the header record ! 543: */ ! 544: ! 545: memcpy(pb+sizeof(IMAGE_COFF_SYMBOLS_HEADER), ! 546: p->iptrs.fptr + DbgDirCoff.PointerToRawData + ! 547: pCoffDbgInfo->LvaToFirstSymbol, cb); ! 548: pCoffDbgInfo->LvaToFirstSymbol = sizeof(IMAGE_COFF_SYMBOLS_HEADER); ! 549: DbgDirCoff.SizeOfData = cb + sizeof(IMAGE_COFF_SYMBOLS_HEADER); ! 550: pCoffDbgInfo->NumberOfLinenumbers = 0; ! 551: pCoffDbgInfo->LvaToFirstLinenumber = 0; ! 552: } ! 553: return; ! 554: } /* ReadDebugInfo() */ ! 555: ! 556: ! 557: ! 558: void ! 559: WriteDebugInfo( ! 560: PPOINTERS p, ! 561: BOOL fAddCV, ! 562: BOOL fStrip ! 563: ) ! 564: /*++ ! 565: ! 566: Routine Description: ! 567: ! 568: This function will go out and read in all of the debug information ! 569: into memory -- this is required because the input and output ! 570: files might be the same, if so then writing out informaiton may ! 571: destory data we need at a later time. ! 572: ! 573: Arguments: ! 574: ! 575: p - Supplies a pointer to the structure describing the debug info file ! 576: ! 577: Return Value: ! 578: ! 579: None. ! 580: ! 581: --*/ ! 582: ! 583: { ! 584: ULONG PointerToDebugData = 0; /* Offset from the start of the file ! 585: * to the current location to write ! 586: * debug information out. ! 587: */ ! 588: ULONG BaseOfDebugData = 0; ! 589: int i; ! 590: PIMAGE_DEBUG_DIRECTORY pDir; ! 591: int flen; ! 592: PIMAGE_DEBUG_DIRECTORY pDbgDir = NULL; ! 593: ! 594: ! 595: if (p->optrs.debugSection) { ! 596: BaseOfDebugData = PointerToDebugData = ! 597: p->optrs.debugSection->PointerToRawData; ! 598: } else if (p->optrs.sepHdr) { ! 599: BaseOfDebugData = PointerToDebugData = ! 600: sizeof(IMAGE_SEPARATE_DEBUG_HEADER) + ! 601: p->optrs.sepHdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) + ! 602: p->optrs.sepHdr->ExportedNamesSize; ! 603: } ! 604: ! 605: ! 606: /* ! 607: * Step 2. If the debug information is mapped, we know this ! 608: * from the section headers, then we may need to write ! 609: * out a new debug director to point to the debug information ! 610: */ ! 611: ! 612: if (fAddCV) { ! 613: if (p->optrs.optHdr) { ! 614: p->optrs.optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]. ! 615: VirtualAddress = p->optrs.debugSection->VirtualAddress; ! 616: p->optrs.optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size += ! 617: sizeof(IMAGE_DEBUG_DIRECTORY); ! 618: } else if (p->optrs.sepHdr) { ! 619: p->optrs.sepHdr->DebugDirectorySize += ! 620: sizeof(IMAGE_DEBUG_DIRECTORY); ! 621: } else { ! 622: exit(1); ! 623: } ! 624: ! 625: if (p->optrs.sepHdr) { ! 626: pDbgDir = (PIMAGE_DEBUG_DIRECTORY) malloc(p->optrs.cDebugDir * sizeof(IMAGE_DEBUG_DIRECTORY)); ! 627: for (i=0; i<p->optrs.cDebugDir; i++) { ! 628: if (p->optrs.rgDebugDir[i] != NULL) { ! 629: pDbgDir[i] = *(p->optrs.rgDebugDir[i]); ! 630: p->optrs.rgDebugDir[i] = &pDbgDir[i]; ! 631: } ! 632: } ! 633: } ! 634: for (i=0; i<p->optrs.cDebugDir; i++) { ! 635: if (p->optrs.rgDebugDir[i]) { ! 636: pDir = (PIMAGE_DEBUG_DIRECTORY) (PointerToDebugData + ! 637: p->optrs.fptr); ! 638: *pDir = *(p->optrs.rgDebugDir[i]); ! 639: p->optrs.rgDebugDir[i] = pDir; ! 640: PointerToDebugData += sizeof(IMAGE_DEBUG_DIRECTORY); ! 641: } ! 642: } ! 643: } ! 644: ! 645: /* ! 646: * For every debug info type, write out the debug information ! 647: * and update any header information required ! 648: */ ! 649: ! 650: for (i=0; i<p->optrs.cDebugDir; i++) { ! 651: if (p->optrs.rgDebugDir[i] != NULL) { ! 652: if (!fStrip || ! 653: (i == IMAGE_DEBUG_TYPE_FPO) || ! 654: (i == IMAGE_DEBUG_TYPE_MISC)) { ! 655: if (p->optrs.rgpbDebugSave[i] != NULL) { ! 656: p->optrs.rgDebugDir[i]->PointerToRawData = ! 657: PointerToDebugData; ! 658: if (p->optrs.debugSection) { ! 659: p->optrs.rgDebugDir[i]->AddressOfRawData = ! 660: p->optrs.debugSection->VirtualAddress + ! 661: PointerToDebugData - BaseOfDebugData; ! 662: } ! 663: memcpy(p->optrs.fptr + PointerToDebugData, ! 664: p->optrs.rgpbDebugSave[i], ! 665: p->optrs.rgDebugDir[i]->SizeOfData); ! 666: ! 667: if ((i == IMAGE_DEBUG_TYPE_COFF) && ! 668: (p->optrs.fileHdr != NULL)) { ! 669: p->optrs.fileHdr->PointerToSymbolTable = ! 670: PointerToDebugData + sizeof(IMAGE_COFF_SYMBOLS_HEADER); ! 671: } ! 672: } ! 673: PointerToDebugData += p->optrs.rgDebugDir[i]->SizeOfData; ! 674: } ! 675: } ! 676: } ! 677: ! 678: if ((PointerToDebugData == BaseOfDebugData) && fStrip) { ! 679: p->optrs.fileHdr->NumberOfSections -= 1; ! 680: } ! 681: ! 682: /* ! 683: * Step 4. Clean up any COFF structures if we are replacing ! 684: * the coff information with CV info. ! 685: */ ! 686: ! 687: if ((p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_COFF] == NULL) && ! 688: (p->optrs.fileHdr != NULL)) { ! 689: /* ! 690: * Since there is no coff debug information -- clean out ! 691: * both fields pointing to the debug info ! 692: */ ! 693: ! 694: p->optrs.fileHdr->PointerToSymbolTable = 0; ! 695: p->optrs.fileHdr->NumberOfSymbols = 0; ! 696: } ! 697: ! 698: /* ! 699: * Step 5. Correct the alignments if needed. If there is ! 700: * a real .debug section in the file (i.e. it is mapped) ! 701: * then update the description of the section. ! 702: */ ! 703: ! 704: if (p->optrs.debugSection) { ! 705: p->optrs.debugSection->SizeOfRawData = ! 706: FileAlign(PointerToDebugData - BaseOfDebugData); ! 707: /* ! 708: * update the optional header with the new image size ! 709: */ ! 710: ! 711: p->optrs.optHdr->SizeOfImage = ! 712: SectionAlign(p->optrs.debugSection->VirtualAddress + ! 713: p->optrs.debugSection->SizeOfRawData); ! 714: p->optrs.optHdr->SizeOfInitializedData += ! 715: p->optrs.debugSection->SizeOfRawData; ! 716: } ! 717: ! 718: /* ! 719: * calculate the new file size ! 720: */ ! 721: ! 722: if (p->optrs.optHdr != NULL) { ! 723: flen = FileAlign(PointerToDebugData); ! 724: } else { ! 725: flen = PointerToDebugData; ! 726: } ! 727: ! 728: /* ! 729: * finally, update the eof pointer and close the file ! 730: */ ! 731: ! 732: UnmapViewOfFile( p->optrs.fptr ); ! 733: ! 734: if (!SetFilePointer( p->optrs.hFile, flen, 0, FILE_BEGIN )) { ! 735: FatalError( ERR_FILE_PTRS ); ! 736: } ! 737: ! 738: if (!SetEndOfFile( p->optrs.hFile )) { ! 739: FatalError( ERR_SET_EOF ); ! 740: } ! 741: ! 742: CloseHandle( p->optrs.hFile ); ! 743: ! 744: /* ! 745: * Exit -- we are done. ! 746: */ ! 747: ! 748: return; ! 749: } /* WriteDebugInfo() */ ! 750: ! 751: ! 752: ! 753: void ! 754: MungeDebugHeadersCoffToCv( ! 755: PPOINTERS p, ! 756: BOOL fAddCV ! 757: ) ! 758: ! 759: /*++ ! 760: ! 761: Routine Description: ! 762: ! 763: ! 764: Arguments: ! 765: ! 766: p - pointer to a POINTERS structure (see cofftocv.h) ! 767: ! 768: Return Value: ! 769: ! 770: void ! 771: ! 772: --*/ ! 773: ! 774: { ! 775: if (!fAddCV) { ! 776: CV_DIR(&p->optrs) = COFF_DIR(&p->optrs); ! 777: COFF_DIR(&p->optrs) = 0; ! 778: } else { ! 779: CV_DIR(&p->optrs) = &DbgDirSpare; ! 780: *(COFF_DIR(&p->optrs)) = *(COFF_DIR(&p->iptrs)); ! 781: }; ! 782: ! 783: *CV_DIR(&p->optrs) = *(COFF_DIR(&p->iptrs)); ! 784: CV_DIR(&p->optrs)->Type = IMAGE_DEBUG_TYPE_CODEVIEW; ! 785: CV_DIR(&p->optrs)->SizeOfData = p->pCvStart.size; ! 786: p->optrs.rgpbDebugSave[IMAGE_DEBUG_TYPE_CODEVIEW] = p->pCvStart.ptr; ! 787: ! 788: return; ! 789: } /* MungeDebugHeadersCoffToCv() */ ! 790: ! 791: ! 792: ! 793: BOOL ! 794: MapOutputFile ( PPOINTERS p, char *fname, int cb ) ! 795: ! 796: /*++ ! 797: ! 798: Routine Description: ! 799: ! 800: Maps the output file specified by the fname argument and saves the ! 801: file handle & file pointer in the POINTERS structure. ! 802: ! 803: ! 804: Arguments: ! 805: ! 806: p - pointer to a POINTERS structure (see cofftocv.h) ! 807: fname - ascii string for the file name ! 808: ! 809: ! 810: Return Value: ! 811: ! 812: TRUE - file mapped ok ! 813: FALSE - file could not be mapped ! 814: ! 815: --*/ ! 816: ! 817: { ! 818: BOOL rval; ! 819: HANDLE hMap = NULL; ! 820: DWORD oSize; ! 821: ! 822: rval = FALSE; ! 823: ! 824: p->optrs.hFile = CreateFile( fname, ! 825: GENERIC_READ | GENERIC_WRITE, ! 826: FILE_SHARE_READ | FILE_SHARE_WRITE, ! 827: NULL, ! 828: OPEN_ALWAYS, ! 829: 0, ! 830: NULL ); ! 831: ! 832: if (p->optrs.hFile == INVALID_HANDLE_VALUE) { ! 833: goto exit; ! 834: } ! 835: ! 836: oSize = p->iptrs.fsize; ! 837: if (p->pCvStart.ptr != NULL) { ! 838: oSize += p->pCvStart.size; ! 839: } ! 840: oSize += cb; ! 841: oSize += p->iptrs.cDebugDir * sizeof(IMAGE_DEBUG_DIRECTORY); ! 842: ! 843: hMap = CreateFileMapping( p->optrs.hFile, NULL, PAGE_READWRITE, ! 844: 0, oSize, NULL ); ! 845: ! 846: if (hMap == NULL) { ! 847: goto exit; ! 848: } ! 849: ! 850: p->optrs.fptr = MapViewOfFile( hMap, FILE_MAP_WRITE, 0, 0, 0 ); ! 851: ! 852: if (p->optrs.fptr == NULL) { ! 853: goto exit; ! 854: } ! 855: rval = TRUE; ! 856: exit: ! 857: return rval; ! 858: } /* MapOutputFile() */ ! 859: ! 860: BOOL ! 861: CalculateOutputFilePointers( PIMAGEPOINTERS pi, PIMAGEPOINTERS po ) ! 862: ! 863: /*++ ! 864: ! 865: Routine Description: ! 866: ! 867: This function calculates the output file pointers based on the ! 868: input file pointers. The same address is used but they are all ! 869: re-based off the output file's file pointer. ! 870: ! 871: Arguments: ! 872: ! 873: p - pointer to a IMAGEPOINTERS structure (see cofftocv.h) ! 874: ! 875: ! 876: Return Value: ! 877: ! 878: TRUE - pointers were created ! 879: FALSE - pointers could not be created ! 880: ! 881: --*/ ! 882: { ! 883: int i; ! 884: ! 885: // fixup the pointers relative the fptr for the output file ! 886: po->dosHdr = (PIMAGE_DOS_HEADER) AdjustPtr(pi->dosHdr); ! 887: po->ntHdr = (PIMAGE_NT_HEADERS) AdjustPtr(pi->ntHdr); ! 888: po->fileHdr = (PIMAGE_FILE_HEADER) AdjustPtr(pi->fileHdr); ! 889: po->optHdr = (PIMAGE_OPTIONAL_HEADER) AdjustPtr(pi->optHdr); ! 890: po->sectionHdrs = (PIMAGE_SECTION_HEADER) AdjustPtr(pi->sectionHdrs); ! 891: po->sepHdr = (PIMAGE_SEPARATE_DEBUG_HEADER) AdjustPtr(pi->sepHdr); ! 892: po->debugSection = (PIMAGE_SECTION_HEADER) AdjustPtr(pi->debugSection); ! 893: po->AllSymbols = (PIMAGE_SYMBOL) AdjustPtr(pi->AllSymbols); ! 894: po->stringTable = (PUCHAR) AdjustPtr(pi->stringTable); ! 895: ! 896: // move the data from the input file to the output file ! 897: memcpy( po->fptr, pi->fptr, pi->fsize ); ! 898: ! 899: po->cDebugDir = pi->cDebugDir; ! 900: po->rgDebugDir = malloc(po->cDebugDir * sizeof(po->rgDebugDir[0])); ! 901: memset(po->rgDebugDir, 0, po->cDebugDir * sizeof(po->rgDebugDir[0])); ! 902: ! 903: for (i=0; i<po->cDebugDir; i++) { ! 904: po->rgDebugDir[i] = (PIMAGE_DEBUG_DIRECTORY) AdjustPtr(pi->rgDebugDir[i]); ! 905: } ! 906: po->rgpbDebugSave = pi->rgpbDebugSave; ! 907: ! 908: /* ! 909: * Point the input stream to the modified coff descriptor ! 910: */ ! 911: ! 912: if (pi->rgDebugDir[IMAGE_DEBUG_TYPE_COFF] != NULL) { ! 913: pi->rgDebugDir[IMAGE_DEBUG_TYPE_COFF] = &DbgDirCoff; ! 914: } ! 915: ! 916: return TRUE; ! 917: } ! 918: ! 919: ! 920: void ! 921: FatalError( ! 922: int idMsg, ! 923: ... ! 924: ) ! 925: /*++ ! 926: ! 927: Routine Description: ! 928: ! 929: Prints a message string to stderr and then exits. ! 930: ! 931: Arguments: ! 932: ! 933: s - message string to be printed ! 934: ! 935: Return Value: ! 936: ! 937: void ! 938: ! 939: --*/ ! 940: ! 941: { ! 942: va_list marker; ! 943: char rgchFormat[256]; ! 944: char rgch[256]; ! 945: ! 946: LoadString(GetModuleHandle(NULL), idMsg, rgchFormat, sizeof(rgchFormat)); ! 947: ! 948: va_start(marker, idMsg); ! 949: vsprintf(rgch, rgchFormat, marker); ! 950: va_end(marker); ! 951: ! 952: fprintf(stderr, "%s\n", rgch); ! 953: ! 954: exit(1); ! 955: } /* FatalError() */ ! 956: ! 957: ! 958: void ! 959: ComputeChecksum( char *szExeFile ) ! 960: ! 961: /*++ ! 962: ! 963: Routine Description: ! 964: ! 965: Computes a new checksum for the image by calling imagehlp.dll ! 966: ! 967: Arguments: ! 968: ! 969: szExeFile - exe file name ! 970: ! 971: ! 972: Return Value: ! 973: ! 974: void ! 975: ! 976: --*/ ! 977: ! 978: { ! 979: DWORD dwHeaderSum = 0; ! 980: DWORD dwCheckSum = 0; ! 981: HANDLE hFile; ! 982: DWORD cb; ! 983: IMAGE_DOS_HEADER dosHdr; ! 984: IMAGE_NT_HEADERS ntHdr; ! 985: ! 986: if (MapFileAndCheckSum(szExeFile, &dwHeaderSum, &dwCheckSum) != CHECKSUM_SUCCESS) { ! 987: FatalError( ERR_CHECKSUM_CALC ); ! 988: } ! 989: ! 990: hFile = CreateFile( szExeFile, ! 991: GENERIC_READ | GENERIC_WRITE, ! 992: FILE_SHARE_READ | FILE_SHARE_WRITE, ! 993: NULL, ! 994: OPEN_EXISTING, ! 995: 0, ! 996: NULL ! 997: ); ! 998: ! 999: // seek to the beginning of the file ! 1000: SetFilePointer( hFile, 0, 0, FILE_BEGIN ); ! 1001: ! 1002: // read in the dos header ! 1003: if ((ReadFile(hFile, &dosHdr, sizeof(dosHdr), &cb, 0) == FALSE) || (cb != sizeof(dosHdr))) { ! 1004: FatalError( ERR_CHECKSUM_CALC ); ! 1005: } ! 1006: ! 1007: // read in the pe header ! 1008: if ((dosHdr.e_magic != IMAGE_DOS_SIGNATURE) || ! 1009: (SetFilePointer(hFile, dosHdr.e_lfanew, 0, FILE_BEGIN) == -1L)) { ! 1010: FatalError( ERR_CHECKSUM_CALC ); ! 1011: } ! 1012: ! 1013: // read in the nt header ! 1014: if ((!ReadFile(hFile, &ntHdr, sizeof(ntHdr), &cb, 0)) || (cb != sizeof(ntHdr))) { ! 1015: FatalError( ERR_CHECKSUM_CALC ); ! 1016: } ! 1017: ! 1018: if (SetFilePointer(hFile, dosHdr.e_lfanew, 0, FILE_BEGIN) == -1L) { ! 1019: FatalError( ERR_CHECKSUM_CALC ); ! 1020: } ! 1021: ! 1022: ntHdr.OptionalHeader.CheckSum = dwCheckSum; ! 1023: ! 1024: if (!WriteFile(hFile, &ntHdr, sizeof(ntHdr), &cb, NULL)) { ! 1025: FatalError( ERR_CHECKSUM_CALC ); ! 1026: } ! 1027: ! 1028: CloseHandle(hFile); ! 1029: return; ! 1030: } ! 1031: ! 1032: ! 1033: void ! 1034: MungeExeName( ! 1035: PPOINTERS p, ! 1036: char * szExeName ! 1037: ) ! 1038: /*++ ! 1039: ! 1040: Routine Description: ! 1041: ! 1042: description-of-function. ! 1043: ! 1044: Arguments: ! 1045: ! 1046: argument-name - Supplies | Returns description of argument. ! 1047: . ! 1048: . ! 1049: ! 1050: Return Value: ! 1051: ! 1052: None. ! 1053: ! 1054: --*/ ! 1055: ! 1056: { ! 1057: PIMAGE_DEBUG_MISC pMiscIn; ! 1058: PIMAGE_DEBUG_MISC pMiscOut; ! 1059: int cb; ! 1060: int i; ! 1061: ! 1062: for (i=0; i<p->iptrs.cDebugDir; i++) { ! 1063: if (p->optrs.rgDebugDir[i] != 0) { ! 1064: *(p->optrs.rgDebugDir[i]) = *(p->iptrs.rgDebugDir[i]); ! 1065: } ! 1066: } ! 1067: ! 1068: pMiscIn = (PIMAGE_DEBUG_MISC) ! 1069: p->iptrs.rgpbDebugSave[IMAGE_DEBUG_TYPE_MISC]; ! 1070: ! 1071: if (p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_MISC] == NULL) { ! 1072: p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_MISC] = &DbgDirSpare; ! 1073: memset(&DbgDirSpare, 0, sizeof(DbgDirSpare)); ! 1074: } ! 1075: ! 1076: pMiscOut = (PIMAGE_DEBUG_MISC) ! 1077: p->optrs.rgpbDebugSave[IMAGE_DEBUG_TYPE_MISC] = ! 1078: malloc(p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_MISC]->SizeOfData + ! 1079: strlen(szExeName)); ! 1080: cb = p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_MISC]->SizeOfData; ! 1081: ! 1082: while ( cb > 0 ) { ! 1083: if (pMiscIn->DataType == IMAGE_DEBUG_MISC_EXENAME) { ! 1084: pMiscOut->DataType = IMAGE_DEBUG_MISC_EXENAME; ! 1085: pMiscOut->Length = (sizeof(IMAGE_DEBUG_MISC) + ! 1086: strlen(szExeName) + 3) & ~3; ! 1087: pMiscOut->Unicode = FALSE; ! 1088: strcpy(&pMiscOut->Data[0], szExeName); ! 1089: szExeName = NULL; ! 1090: } else { ! 1091: memcpy(pMiscOut, pMiscIn, pMiscIn->Length); ! 1092: } ! 1093: ! 1094: p->optrs.rgDebugDir[IMAGE_DEBUG_TYPE_MISC]->SizeOfData += ! 1095: (pMiscOut->Length - pMiscIn->Length); ! 1096: ! 1097: cb -= pMiscIn->Length; ! 1098: pMiscIn = (PIMAGE_DEBUG_MISC) (((char *) pMiscIn) + pMiscIn->Length); ! 1099: pMiscOut = (PIMAGE_DEBUG_MISC) (((char *) pMiscOut) + pMiscOut->Length); ! 1100: } ! 1101: ! 1102: if (szExeName) { ! 1103: pMiscOut->DataType = IMAGE_DEBUG_MISC_EXENAME; ! 1104: pMiscOut->Length = (sizeof(IMAGE_DEBUG_MISC) + ! 1105: strlen(szExeName) + 3) & ~3; ! 1106: pMiscOut->Unicode = FALSE; ! 1107: strcpy(&pMiscOut->Data[0], szExeName); ! 1108: } ! 1109: ! 1110: return; ! 1111: } /* MungeExeName() */ ! 1112: ! 1113: ! 1114: /*** DoCoffToCv ! 1115: * ! 1116: * ! 1117: */ ! 1118: ! 1119: void DoCoffToCv(char * szInput, char * szOutput, BOOL fAddCV) ! 1120: { ! 1121: POINTERS p; ! 1122: ! 1123: /* ! 1124: * Do default checking ! 1125: */ ! 1126: ! 1127: if (szOutput == NULL) { ! 1128: szOutput = szInput; ! 1129: } ! 1130: ! 1131: /* ! 1132: * Open the input file name and setup the pointers into the file ! 1133: */ ! 1134: ! 1135: if (!MapInputFile( &p, NULL, szInput )) { ! 1136: FatalError( ERR_OPEN_INPUT_FILE, szInput ); ! 1137: } ! 1138: ! 1139: /* ! 1140: * Now, if we thing we are playing with PE exes then we need ! 1141: * to setup the pointers into the map file ! 1142: */ ! 1143: ! 1144: if (!CalculateNtImagePointers( &p.iptrs )) { ! 1145: FatalError( ERR_INVALID_PE, szInput ); ! 1146: } ! 1147: ! 1148: /* ! 1149: * We are about to try and do the coff to cv symbol conversion. ! 1150: * ! 1151: * Verify that the operation is legal. ! 1152: * ! 1153: * 1. We need to have coff debug information to start with ! 1154: * 2. If the debug info is not mapped then we must not ! 1155: * be trying to add CodeView info. ! 1156: */ ! 1157: ! 1158: if ((p.iptrs.AllSymbols == NULL) || (COFF_DIR(&p.iptrs) == NULL)) { ! 1159: FatalError( ERR_NO_COFF ); ! 1160: } ! 1161: ! 1162: if (fAddCV && (p.iptrs.debugSection == 0) && (p.iptrs.sepHdr == NULL)) { ! 1163: FatalError( ERR_NOT_MAPPED ); ! 1164: } ! 1165: ! 1166: /* ! 1167: * Now go out an preform the acutal conversion. ! 1168: */ ! 1169: ! 1170: if (!ConvertCoffToCv( &p )) { ! 1171: FatalError( ERR_COFF_TO_CV ); ! 1172: } ! 1173: ! 1174: /* ! 1175: * Read in any additional debug information in the file ! 1176: */ ! 1177: ! 1178: ReadDebugInfo(&p); ! 1179: ! 1180: /* ! 1181: * Open the output file and adjust the pointers so that ! 1182: * we are ok. ! 1183: */ ! 1184: ! 1185: if (!MapOutputFile( &p, szOutput, 0 )) { ! 1186: FatalError( ERR_MAP_FILE, szOutput ); ! 1187: } ! 1188: ! 1189: CalculateOutputFilePointers( &p.iptrs, &p.optrs ); ! 1190: ! 1191: /* ! 1192: * Munge the various debug information structures ! 1193: * to preform the correct operations ! 1194: */ ! 1195: ! 1196: MungeDebugHeadersCoffToCv( &p, fAddCV ); ! 1197: ! 1198: /* ! 1199: * Write out the debug information to the end of the exe ! 1200: */ ! 1201: ! 1202: WriteDebugInfo( &p, fAddCV, FALSE ); ! 1203: ! 1204: /* ! 1205: * and finally compute the checksum ! 1206: */ ! 1207: ! 1208: if (p.iptrs.fileHdr != NULL) { ! 1209: ComputeChecksum( szOutput ); ! 1210: } ! 1211: ! 1212: return; ! 1213: } /* DoCoffToCv() */ ! 1214: ! 1215: /*** DoSymToCv ! 1216: * ! 1217: */ ! 1218: ! 1219: void DoSymToCv(char * szInput, char * szOutput, char * szDbg, char * szSym) ! 1220: { ! 1221: POINTERS p; ! 1222: HANDLE hFile; ! 1223: DWORD cb; ! 1224: OFSTRUCT ofs; ! 1225: ! 1226: /* ! 1227: * Open the input file name and setup the pointers into the file ! 1228: */ ! 1229: ! 1230: if (!MapInputFile( &p, NULL, szSym )) { ! 1231: FatalError(ERR_OPEN_INPUT_FILE, szSym); ! 1232: } ! 1233: ! 1234: /* ! 1235: * Now preform the desired operation ! 1236: */ ! 1237: ! 1238: if ((szOutput == NULL) && (szDbg == NULL)) { ! 1239: szOutput = szInput; ! 1240: } ! 1241: ! 1242: ConvertSymToCv( &p ); ! 1243: ! 1244: if (szOutput) { ! 1245: if (szOutput != szInput) { ! 1246: if (OpenFile(szInput, &ofs, OF_EXIST) == 0) { ! 1247: FatalError(ERR_OPEN_INPUT_FILE, szInput); ! 1248: } ! 1249: if (CopyFile(szInput, szOutput, FALSE) == 0) { ! 1250: FatalError(ERR_OPEN_WRITE_FILE, szOutput); ! 1251: } ! 1252: } ! 1253: hFile = CreateFile(szOutput, GENERIC_WRITE, 0, NULL, ! 1254: CREATE_ALWAYS, ! 1255: FILE_ATTRIBUTE_NORMAL, NULL); ! 1256: if (hFile == INVALID_HANDLE_VALUE) { ! 1257: FatalError(ERR_OPEN_WRITE_FILE, szOutput); ! 1258: } ! 1259: SetFilePointer(hFile, 0, 0, FILE_END); ! 1260: } else if (szDbg) { ! 1261: hFile = CreateFile(szDbg, GENERIC_WRITE, 0, NULL, ! 1262: OPEN_ALWAYS, ! 1263: FILE_ATTRIBUTE_NORMAL, NULL); ! 1264: if (hFile == INVALID_HANDLE_VALUE) { ! 1265: FatalError(ERR_OPEN_WRITE_FILE, szDbg); ! 1266: } ! 1267: } ! 1268: ! 1269: WriteFile(hFile, p.pCvStart.ptr, p.pCvStart.size, &cb, NULL); ! 1270: CloseHandle(hFile); ! 1271: ! 1272: return; ! 1273: } /* DoSymToCv() */ ! 1274: ! 1275: ! 1276: void DoNameChange(char * szInput, char * szOutput, char * szNewName) ! 1277: { ! 1278: POINTERS p; ! 1279: ! 1280: /* ! 1281: * Open the input file name and setup the pointers into the file ! 1282: */ ! 1283: ! 1284: if (!MapInputFile( &p, NULL, szInput )) { ! 1285: FatalError(ERR_OPEN_INPUT_FILE, szInput); ! 1286: } ! 1287: ! 1288: /* ! 1289: * Now, if we thing we are playing with PE exes then we need ! 1290: * to setup the pointers into the map file ! 1291: */ ! 1292: ! 1293: if (!CalculateNtImagePointers( &p.iptrs )) { ! 1294: FatalError(ERR_INVALID_PE, szInput); ! 1295: } ! 1296: ! 1297: /* ! 1298: * Now preform the desired operation ! 1299: */ ! 1300: ! 1301: if (szOutput == NULL) { ! 1302: szOutput = szInput; ! 1303: } ! 1304: ! 1305: if (szNewName == NULL) { ! 1306: szNewName = szOutput; ! 1307: } ! 1308: ! 1309: if (p.iptrs.sepHdr != NULL) { ! 1310: FatalError(ERR_EDIT_DBG_FILE); ! 1311: } ! 1312: ! 1313: /* ! 1314: * Read in all of the debug information ! 1315: */ ! 1316: ! 1317: ReadDebugInfo(&p); ! 1318: ! 1319: /* ! 1320: * Open the output file and adjust the pointers. ! 1321: */ ! 1322: ! 1323: if (!MapOutputFile(&p, szOutput, ! 1324: sizeof(szNewName) * 2 + sizeof(IMAGE_DEBUG_MISC))) { ! 1325: FatalError(ERR_MAP_FILE, szOutput); ! 1326: } ! 1327: ! 1328: CalculateOutputFilePointers(&p.iptrs, &p.optrs); ! 1329: ! 1330: /* ! 1331: * Munge the name of the file ! 1332: */ ! 1333: ! 1334: MungeExeName(&p, szNewName); ! 1335: ! 1336: /* ! 1337: * Write out the debug information to the end of the exe ! 1338: */ ! 1339: ! 1340: WriteDebugInfo(&p, FALSE, FALSE); ! 1341: ! 1342: /* ! 1343: * and finally compute the checksum ! 1344: */ ! 1345: ! 1346: if (p.iptrs.fileHdr != NULL) { ! 1347: ComputeChecksum( szOutput ); ! 1348: } ! 1349: ! 1350: return; ! 1351: } /* DoNameChange() */ ! 1352: ! 1353: ! 1354: void MungeStrip(PPOINTERS p, BOOL fPartial) ! 1355: { ! 1356: PIMAGE_SECTION_HEADER pSection; ! 1357: ULONG flen; ! 1358: ! 1359: if (p->iptrs.debugSection == NULL) { ! 1360: /* unmapped */ ! 1361: return; ! 1362: } ! 1363: ! 1364: /* ! 1365: * If the last section is not the debug section then ! 1366: * we can't do this. ! 1367: */ ! 1368: ! 1369: pSection = &p->optrs.sectionHdrs[p->iptrs.numberOfSections-1]; ! 1370: if (p->optrs.debugSection != pSection) { ! 1371: exit(1); ! 1372: } ! 1373: pSection -= 1; ! 1374: ! 1375: /* ! 1376: * If full strip ---- ! 1377: * Reduced the number of sections by one, but don't bother ! 1378: * actucally removing the section descriptor, its not worth ! 1379: * the time. ! 1380: */ ! 1381: ! 1382: if (!fPartial) { ! 1383: p->optrs.numberOfSections -= 1; ! 1384: p->optrs.fileHdr->NumberOfSections -= 1; ! 1385: ! 1386: /* ! 1387: * If we are doing a full strip then clear out all pointers ! 1388: * to debug info ! 1389: */ ! 1390: ! 1391: p->optrs.optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0; ! 1392: p->optrs.optHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0; ! 1393: p->optrs.fileHdr->PointerToSymbolTable = 0; ! 1394: p->optrs.fileHdr->NumberOfSymbols = 0; ! 1395: ! 1396: p->optrs.optHdr->SizeOfImage = SectionAlign(pSection->VirtualAddress + ! 1397: pSection->SizeOfRawData); ! 1398: p->optrs.optHdr->SizeOfInitializedData -= ! 1399: p->optrs.debugSection->SizeOfRawData; ! 1400: ! 1401: flen = FileAlign(pSection->VirtualAddress + pSection->SizeOfRawData ); ! 1402: UnmapViewOfFile( p->optrs.fptr ); ! 1403: ! 1404: if (!SetFilePointer( p->optrs.hFile, flen, 0, FILE_BEGIN )) { ! 1405: FatalError(ERR_FILE_PTRS); ! 1406: } ! 1407: ! 1408: if (!SetEndOfFile( p->optrs.hFile )) { ! 1409: FatalError( ERR_SET_EOF ); ! 1410: } ! 1411: ! 1412: CloseHandle( p->optrs.hFile ); ! 1413: ! 1414: return; ! 1415: } ! 1416: ! 1417: /* ! 1418: * Partial strip ! 1419: */ ! 1420: ! 1421: p->optrs.fileHdr->PointerToSymbolTable = 0; ! 1422: p->optrs.fileHdr->NumberOfSymbols = 0; ! 1423: ! 1424: WriteDebugInfo( p, FALSE, TRUE ); ! 1425: ! 1426: return; ! 1427: } /* MungeStrip() */ ! 1428: ! 1429: void DoStrip(char * szInput, char * szOutput) ! 1430: { ! 1431: POINTERS p; ! 1432: ! 1433: if (szOutput == NULL) { ! 1434: szOutput = szInput; ! 1435: } ! 1436: ! 1437: /* ! 1438: * Open the input file and setup the pointers into it. ! 1439: */ ! 1440: ! 1441: if (!MapInputFile(&p, NULL, szInput)) { ! 1442: FatalError(ERR_OPEN_INPUT_FILE, szInput); ! 1443: } ! 1444: ! 1445: /* ! 1446: * Now, setup the rest of the input points ! 1447: */ ! 1448: ! 1449: if (!CalculateNtImagePointers(&p.iptrs)) { ! 1450: FatalError(ERR_INVALID_PE, szInput); ! 1451: } ! 1452: ! 1453: /* ! 1454: * Open the output file and adjust the pointers ! 1455: */ ! 1456: ! 1457: if (!MapOutputFile(&p, szOutput, 0)) { ! 1458: FatalError(ERR_MAP_FILE, szOutput); ! 1459: } ! 1460: ! 1461: CalculateOutputFilePointers(&p.iptrs, &p.optrs); ! 1462: ! 1463: /* ! 1464: * Munge the file headers ! 1465: */ ! 1466: ! 1467: MungeStrip(&p, FALSE); ! 1468: ! 1469: ComputeChecksum(szOutput); ! 1470: ! 1471: return; ! 1472: } /* DoStrip() */ ! 1473: ! 1474: void DoExtract(char * szInput, char * szOutput, char * szDbgFile) ! 1475: { ! 1476: IMAGE_SEPARATE_DEBUG_HEADER sepHdr; ! 1477: DWORD * rgobDbgDir; ! 1478: PIMAGE_DEBUG_DIRECTORY rgDbgDir; ! 1479: POINTERS p; ! 1480: HANDLE hFile; ! 1481: int cb; ! 1482: int i; ! 1483: DWORD BaseOfDebugData; ! 1484: DWORD PointerToDebugData; ! 1485: ! 1486: if (!MapInputFile(&p, NULL, szInput)) { ! 1487: FatalError(ERR_OPEN_INPUT_FILE, szInput); ! 1488: } ! 1489: ! 1490: if (!CalculateNtImagePointers(&p.iptrs)) { ! 1491: FatalError(ERR_INVALID_PE, szInput); ! 1492: } ! 1493: ! 1494: if (szOutput == NULL) { ! 1495: szOutput = szInput; ! 1496: } ! 1497: ! 1498: if (!MapOutputFile(&p, szOutput, 0)) { ! 1499: FatalError(ERR_MAP_FILE, szOutput); ! 1500: } ! 1501: ! 1502: ReadDebugInfo(&p); ! 1503: ! 1504: ! 1505: CalculateOutputFilePointers(&p.iptrs, &p.optrs); ! 1506: ! 1507: /* ! 1508: * Open the DBG file to be dumped ! 1509: */ ! 1510: ! 1511: if (szDbgFile == NULL) { ! 1512: char rgchDrive[_MAX_DRIVE]; ! 1513: char rgchPath[_MAX_PATH]; ! 1514: char rgchBase[_MAX_FNAME]; ! 1515: ! 1516: _splitpath(szInput, rgchDrive, rgchPath, rgchBase, NULL); ! 1517: szDbgFile = malloc(strlen(rgchDrive) + strlen(rgchPath) + ! 1518: strlen(rgchBase) + 5); ! 1519: strcpy(szDbgFile, rgchDrive); ! 1520: strcat(szDbgFile, rgchPath); ! 1521: strcat(szDbgFile, rgchBase); ! 1522: strcat(szDbgFile, ".DBG"); ! 1523: } ! 1524: ! 1525: hFile = CreateFile(szDbgFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, ! 1526: FILE_ATTRIBUTE_NORMAL, NULL); ! 1527: if (hFile == INVALID_HANDLE_VALUE) { ! 1528: FatalError(ERR_OPEN_WRITE_FILE, szDbgFile); ! 1529: } ! 1530: ! 1531: /* ! 1532: * Create a header for the Dbg File ! 1533: */ ! 1534: ! 1535: sepHdr.Signature = IMAGE_SEPARATE_DEBUG_SIGNATURE; ! 1536: sepHdr.Flags = 0; ! 1537: sepHdr.Machine = p.optrs.fileHdr->Machine; ! 1538: sepHdr.Characteristics = 0; ! 1539: sepHdr.TimeDateStamp = 0; ! 1540: sepHdr.CheckSum = 0; ! 1541: sepHdr.ImageBase = 0; ! 1542: sepHdr.SizeOfImage = 0; ! 1543: sepHdr.NumberOfSections = p.iptrs.numberOfSections; ! 1544: sepHdr.ExportedNamesSize = 0; ! 1545: sepHdr.DebugDirectorySize = 0; ! 1546: ! 1547: WriteFile(hFile, &sepHdr, sizeof(sepHdr), &cb, NULL); ! 1548: ! 1549: /* ! 1550: * Put out the new section headers ! 1551: */ ! 1552: ! 1553: for (i=0; i<p.iptrs.numberOfSections; i++) { ! 1554: WriteFile(hFile, &p.iptrs.sectionHdrs[i], sizeof(IMAGE_SECTION_HEADER), ! 1555: &cb, NULL); ! 1556: } ! 1557: ! 1558: /* ! 1559: * Put out the export table ! 1560: */ ! 1561: ! 1562: for (i=0; i<p.iptrs.numberOfSections; i++) { ! 1563: if (strcmp(p.iptrs.sectionHdrs[i].Name, ".edata") == 0) { ! 1564: WriteFile(hFile, ! 1565: p.iptrs.fptr + p.iptrs.sectionHdrs[i].PointerToRawData, ! 1566: p.iptrs.sectionHdrs[i].SizeOfRawData, &cb, NULL); ! 1567: sepHdr.ExportedNamesSize = p.iptrs.sectionHdrs[i].SizeOfRawData; ! 1568: break; ! 1569: } ! 1570: } ! 1571: ! 1572: /* ! 1573: * Put out the new dbg directory headers ! 1574: */ ! 1575: ! 1576: BaseOfDebugData = PointerToDebugData = ! 1577: SetFilePointer(hFile, 0, 0, FILE_CURRENT); ! 1578: ! 1579: rgobDbgDir = (DWORD *) malloc(p.optrs.cDebugDir * sizeof(DWORD)); ! 1580: rgDbgDir = (PIMAGE_DEBUG_DIRECTORY) ! 1581: malloc(p.optrs.cDebugDir * sizeof(IMAGE_DEBUG_DIRECTORY)); ! 1582: memset(rgobDbgDir, 0, p.optrs.cDebugDir * sizeof(DWORD)); ! 1583: memset(rgDbgDir, 0, p.optrs.cDebugDir * sizeof(IMAGE_DEBUG_DIRECTORY)); ! 1584: ! 1585: for (i=0; i<p.iptrs.cDebugDir; i++) { ! 1586: if (p.iptrs.rgDebugDir[i] != NULL) { ! 1587: WriteFile(hFile, p.iptrs.rgDebugDir[i], ! 1588: sizeof(IMAGE_DEBUG_DIRECTORY), &cb, NULL); ! 1589: rgobDbgDir[i] = PointerToDebugData; ! 1590: rgDbgDir[i] = *(p.iptrs.rgDebugDir[i]); ! 1591: PointerToDebugData += sizeof(IMAGE_DEBUG_DIRECTORY); ! 1592: sepHdr.DebugDirectorySize += sizeof(IMAGE_DEBUG_DIRECTORY); ! 1593: } ! 1594: } ! 1595: ! 1596: /* ! 1597: * Write out debug info ! 1598: */ ! 1599: ! 1600: for (i=0; i<p.iptrs.cDebugDir; i++) { ! 1601: if (p.iptrs.rgDebugDir[i] != NULL) { ! 1602: p.optrs.rgDebugDir[i]->AddressOfRawData = 0; ! 1603: rgDbgDir[i].AddressOfRawData = 0; ! 1604: p.optrs.rgDebugDir[i]->PointerToRawData = ! 1605: rgDbgDir[i].PointerToRawData = ! 1606: SetFilePointer(hFile, 0, 0, FILE_CURRENT); ! 1607: WriteFile(hFile, p.iptrs.rgpbDebugSave[i], rgDbgDir[i].SizeOfData, ! 1608: &cb, NULL); ! 1609: } ! 1610: } ! 1611: ! 1612: ! 1613: /* ! 1614: * ! 1615: */ ! 1616: ! 1617: p.optrs.fileHdr->Characteristics |= IMAGE_FILE_DEBUG_STRIPPED; ! 1618: MungeStrip(&p, TRUE); ! 1619: ! 1620: ComputeChecksum(szOutput); ! 1621: ! 1622: UnmapViewOfFile( p.iptrs.fptr ); ! 1623: CloseHandle( p.iptrs.hFile); ! 1624: ! 1625: if (!MapInputFile(&p, NULL, szOutput)) { ! 1626: FatalError(ERR_OPEN_INPUT_FILE, szOutput); ! 1627: } ! 1628: ! 1629: if (!CalculateNtImagePointers(&p.iptrs)) { ! 1630: FatalError(ERR_INVALID_PE, szOutput); ! 1631: } ! 1632: ! 1633: /* ! 1634: * Correct the header and the debug directory records ! 1635: */ ! 1636: ! 1637: sepHdr.Characteristics = p.iptrs.fileHdr->Characteristics; ! 1638: sepHdr.TimeDateStamp = p.iptrs.fileHdr->TimeDateStamp; ! 1639: sepHdr.CheckSum = p.iptrs.optHdr->CheckSum; ! 1640: sepHdr.ImageBase = p.iptrs.optHdr->ImageBase; ! 1641: sepHdr.SizeOfImage = p.iptrs.optHdr->SizeOfImage; ! 1642: ! 1643: SetFilePointer(hFile, 0, 0, FILE_BEGIN); ! 1644: WriteFile(hFile, &sepHdr, sizeof(sepHdr), &cb, NULL); ! 1645: SetFilePointer(hFile, BaseOfDebugData, 0, FILE_BEGIN); ! 1646: for (i=0; i<p.iptrs.cDebugDir; i++) { ! 1647: if (p.iptrs.rgDebugDir[i] != NULL) { ! 1648: WriteFile(hFile, &rgDbgDir[i], ! 1649: sizeof(IMAGE_DEBUG_DIRECTORY), &cb, NULL); ! 1650: } ! 1651: } ! 1652: ! 1653: UnmapViewOfFile( p.iptrs.fptr ); ! 1654: CloseHandle( p.iptrs.hFile); ! 1655: CloseHandle(hFile); ! 1656: ! 1657: return; ! 1658: } /* DoExtract() */ ! 1659: ! 1660: void DoJoin(char * szInput, char * szOutput, char * szDbgFile) ! 1661: { ! 1662: } /* DoJoin() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.