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.

239 lines
6.6 KiB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <windows.h>
  4. #include <imagehlp.h>
  5. #include <cvinfo.h>
  6. #include <private.h>
  7. extern "C"
  8. BOOL
  9. IMAGEAPI
  10. CopyPdb(
  11. CHAR const * szSrcPdb,
  12. CHAR const * szDestPdb,
  13. BOOL StripPrivate
  14. );
  15. BOOL
  16. StripCv(
  17. PSZ szImage
  18. );
  19. void __cdecl main(int argc, char *argv[]);
  20. void Usage(void);
  21. void
  22. Usage (void)
  23. {
  24. puts("USAGE: StripCV <imagename>\n"
  25. "\tRemove non-public CV info from an image.\n");
  26. }
  27. void __cdecl
  28. main(
  29. int argc,
  30. char *argv[])
  31. {
  32. int i;
  33. if (argc < 2) {
  34. Usage();
  35. exit(1);
  36. }
  37. for (i = 1; i < argc; i++) {
  38. StripCv(argv[i]);
  39. }
  40. }
  41. BOOL
  42. StripCv(
  43. PSZ szImage
  44. )
  45. {
  46. PCHAR CvDebugData;
  47. unsigned int i, NumberOfDebugDirectories;
  48. ULONG DebugDirectorySize, NewCvSize = 0, CvDebugSize;
  49. PCHAR NewCvData;
  50. HANDLE FileHandle, hMappedFile;
  51. PVOID DebugDirectories, ImageBase;
  52. PIMAGE_NT_HEADERS NtHeaders;
  53. PIMAGE_DEBUG_DIRECTORY DebugDirectory;
  54. BOOL fRemoveCV = FALSE;
  55. BOOL fDbgFile = FALSE;
  56. ULONG *pDebugSize, FileSize;
  57. BOOL RC = TRUE;
  58. FileHandle = CreateFile(
  59. szImage,
  60. GENERIC_READ | GENERIC_WRITE,
  61. FILE_SHARE_READ,
  62. NULL,
  63. OPEN_EXISTING,
  64. 0,
  65. NULL );
  66. if (FileHandle == INVALID_HANDLE_VALUE) {
  67. printf("Error: Unable to open %s - rc: %d\n", szImage, GetLastError());
  68. RC = FALSE;
  69. goto cleanup1;
  70. }
  71. FileSize = GetFileSize(FileHandle, NULL);
  72. hMappedFile = CreateFileMapping( FileHandle, NULL, PAGE_READWRITE, 0, 0, NULL );
  73. if (!hMappedFile) {
  74. printf("Error: Unable to create read/write map on %s - rc: %d\n", szImage, GetLastError());
  75. RC = FALSE;
  76. goto cleanup2;
  77. }
  78. ImageBase = MapViewOfFile( hMappedFile, FILE_MAP_WRITE, 0, 0, 0 );
  79. if (!ImageBase) {
  80. printf("Error: Unable to Map view of file %s - rc: %d\n", szImage, GetLastError());
  81. RC = FALSE;
  82. goto cleanup3;
  83. }
  84. if (*(USHORT *)ImageBase == IMAGE_SEPARATE_DEBUG_SIGNATURE) {
  85. fDbgFile = TRUE;
  86. PIMAGE_SEPARATE_DEBUG_HEADER DbgFile = (PIMAGE_SEPARATE_DEBUG_HEADER) ImageBase;
  87. DebugDirectories = (PIMAGE_DEBUG_DIRECTORY)((PUCHAR)ImageBase +
  88. sizeof(IMAGE_SEPARATE_DEBUG_HEADER) +
  89. (DbgFile->NumberOfSections * sizeof(IMAGE_SECTION_HEADER)) +
  90. DbgFile->ExportedNamesSize );
  91. pDebugSize = &(DbgFile->DebugDirectorySize);
  92. DebugDirectorySize = DbgFile->DebugDirectorySize;
  93. } else {
  94. NtHeaders = ImageNtHeader( ImageBase );
  95. if (NtHeaders == NULL) {
  96. printf("Error: %s is not an NT image\n", szImage);
  97. RC = FALSE;
  98. goto cleanup4;
  99. }
  100. DebugDirectories =
  101. ImageDirectoryEntryToData(
  102. ImageBase,
  103. FALSE,
  104. IMAGE_DIRECTORY_ENTRY_DEBUG,
  105. &DebugDirectorySize );
  106. pDebugSize = &(NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size);
  107. }
  108. if (DebugDirectories == NULL || DebugDirectorySize == 0)
  109. {
  110. printf("Warning: No debug info found on %s\n", szImage);
  111. RC = FALSE;
  112. goto cleanup4;
  113. }
  114. DebugDirectory = (PIMAGE_DEBUG_DIRECTORY) DebugDirectories;
  115. NumberOfDebugDirectories = DebugDirectorySize / sizeof( IMAGE_DEBUG_DIRECTORY );
  116. CvDebugData = NULL;
  117. for (i=0; i < NumberOfDebugDirectories; i++) {
  118. if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
  119. CvDebugData = (PCHAR)ImageBase + DebugDirectory->PointerToRawData;
  120. CvDebugSize = DebugDirectory->SizeOfData;
  121. break;
  122. }
  123. // Zero out the Fixup data
  124. if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_FIXUP) {
  125. printf("Info: Removing Fixup data from %s\n", szImage);
  126. RtlZeroMemory(((PUCHAR)ImageBase + DebugDirectory->PointerToRawData),
  127. DebugDirectory->SizeOfData);
  128. DebugDirectory = DebugDirectory+1;
  129. *pDebugSize -= sizeof(IMAGE_DEBUG_DIRECTORY);
  130. } else {
  131. DebugDirectory++;
  132. }
  133. }
  134. if (CvDebugData == NULL) {
  135. printf("Info: No CV Debug found on %s\n", szImage);
  136. RC = FALSE;
  137. goto cleanup5;
  138. }
  139. if (RemovePrivateCvSymbolicEx(CvDebugData, CvDebugSize, &NewCvData, &NewCvSize)) {
  140. // No CV debug in new size. Let's check for PDB's. If so, copy the pdb to
  141. // <filename>pub
  142. typedef struct NB10I { // NB10 debug info
  143. DWORD nb10; // NB10
  144. DWORD off; // offset, always 0
  145. DWORD sig;
  146. DWORD age;
  147. } NB10I;
  148. NB10I *NB10Data = (NB10I *)CvDebugData;
  149. PCHAR szPrivatePdb;
  150. CHAR szPublicPdb[_MAX_PATH];
  151. if (NB10Data->nb10 == '01BN') {
  152. // It has a NB10 signature. Get the name.
  153. szPrivatePdb = CvDebugData + sizeof(NB10I);
  154. strcpy(szPublicPdb, szPrivatePdb);
  155. strcat(szPublicPdb, "pub");
  156. CopyPdb(szPrivatePdb, szPublicPdb, TRUE);
  157. } else {
  158. printf("Info: CV types info stripped from %s\n", szImage);
  159. }
  160. }
  161. RtlCopyMemory(CvDebugData, NewCvData, NewCvSize);
  162. DebugDirectory = (PIMAGE_DEBUG_DIRECTORY) DebugDirectories;
  163. for (i=0; i < NumberOfDebugDirectories; i++) {
  164. if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
  165. if (i+1 == NumberOfDebugDirectories) {
  166. // This is the simple case. cv is the last entry. Simply truncate the image.
  167. FileSize += NewCvSize - DebugDirectory->SizeOfData;
  168. }
  169. DebugDirectory->SizeOfData = NewCvSize;
  170. break;
  171. }
  172. DebugDirectory++;
  173. }
  174. cleanup5:
  175. // All done.
  176. if (!fDbgFile) {
  177. PIMAGE_NT_HEADERS pHdr = NULL;
  178. DWORD SumHeader;
  179. DWORD SumTotal;
  180. pHdr = CheckSumMappedFile(ImageBase, FileSize, &SumHeader, &SumTotal);
  181. if (pHdr != NULL) {
  182. pHdr->OptionalHeader.CheckSum = SumTotal;
  183. }
  184. }
  185. FlushViewOfFile(ImageBase, NULL);
  186. cleanup4:
  187. UnmapViewOfFile(ImageBase);
  188. cleanup3:
  189. CloseHandle(hMappedFile);
  190. cleanup2:
  191. SetFilePointer(FileHandle, FileSize, NULL, FILE_BEGIN);
  192. SetEndOfFile(FileHandle);
  193. CloseHandle(FileHandle);
  194. cleanup1:
  195. return(RC);
  196. }