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.

464 lines
14 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. editsym.c
  5. Abstract:
  6. This is the main source file for the EDITSYM utility program. This
  7. program can be used to extract the debugging information contained in
  8. a separate .DBG file and put it back to the original image file.
  9. Author:
  10. HonWah Chan 21-March-1994
  11. Revision History:
  12. --*/
  13. #include <private.h>
  14. BOOL fVerbose;
  15. LPSTR FilePart;
  16. UCHAR CurrentImageName[ MAX_PATH ];
  17. UCHAR DbgFileName[ MAX_PATH ];
  18. void
  19. Usage( void )
  20. {
  21. fputs( "Function: Extract debugging information contained in .dbg file\n"
  22. "\tand put it back in the original image file\n\n"
  23. "Usage: EDITSYM [-?] [-s symbol-filename] image-name\n"
  24. "\t\t[-?] display this message\n"
  25. "\t\t[-s symbol-filename] - name of the .DBG file. Default is the same\n"
  26. "\t\t name and location as the image file.\n\n"
  27. "\tE.G. EditSym -s Perfmon.dbg Perfmon.exe\n", stderr );
  28. exit( 1 );
  29. }
  30. BOOL EditSymbols(
  31. LPSTR pImageName,
  32. LPSTR pDbgFileName
  33. )
  34. {
  35. PIMAGE_NT_HEADERS NtHeaders;
  36. HANDLE FileHandle, SymbolFileHandle;
  37. HANDLE hMappedFile;
  38. LPVOID ImageBase;
  39. PIMAGE_DEBUG_DIRECTORY DebugDirectories;
  40. PIMAGE_DEBUG_DIRECTORY DebugDirectoriesSave;
  41. DWORD DebugDirectorySize, NumberOfDebugDirectories;
  42. DWORD SavedErrorCode;
  43. PIMAGE_DEBUG_DIRECTORY DebugDirectory;
  44. DWORD i;
  45. DWORD NewFileSize, HeaderSum, CheckSum;
  46. DWORD DebugDataSize;
  47. LPBYTE DebugData;
  48. IMAGE_SEPARATE_DEBUG_HEADER DbgFileHeader;
  49. ImageBase = NULL;
  50. hMappedFile = 0;
  51. FileHandle = SymbolFileHandle = 0;
  52. DebugDirectoriesSave = NULL;
  53. //
  54. // open and map the file.
  55. //
  56. FileHandle = CreateFile( pImageName,
  57. GENERIC_READ | GENERIC_WRITE,
  58. FILE_SHARE_READ,
  59. NULL,
  60. OPEN_EXISTING,
  61. 0,
  62. NULL
  63. );
  64. if (FileHandle == INVALID_HANDLE_VALUE) {
  65. return FALSE;
  66. }
  67. hMappedFile = CreateFileMapping( FileHandle,
  68. NULL,
  69. PAGE_READWRITE,
  70. 0,
  71. 0,
  72. NULL
  73. );
  74. if (!hMappedFile) {
  75. CloseHandle( FileHandle );
  76. return FALSE;
  77. }
  78. ImageBase = MapViewOfFile( hMappedFile,
  79. FILE_MAP_WRITE,
  80. 0,
  81. 0,
  82. 0
  83. );
  84. if (!ImageBase) {
  85. CloseHandle( hMappedFile );
  86. CloseHandle( FileHandle );
  87. return FALSE;
  88. }
  89. //
  90. // Everything is mapped. Now check the image and find nt image headers
  91. //
  92. NtHeaders = ImageNtHeader( ImageBase );
  93. if (NtHeaders == NULL) {
  94. SetLastError( ERROR_BAD_EXE_FORMAT );
  95. goto nosyms;
  96. }
  97. if ((NtHeaders->OptionalHeader.MajorLinkerVersion < 3) &&
  98. (NtHeaders->OptionalHeader.MinorLinkerVersion < 5)
  99. ) {
  100. SetLastError( ERROR_BAD_EXE_FORMAT );
  101. goto nosyms;
  102. }
  103. if (!(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)) {
  104. SetLastError( ERROR_ALREADY_ASSIGNED );
  105. goto nosyms;
  106. }
  107. DebugDirectories = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryEntryToData( ImageBase,
  108. FALSE,
  109. IMAGE_DIRECTORY_ENTRY_DEBUG,
  110. &DebugDirectorySize
  111. );
  112. if (!DebugDirectoryIsUseful(DebugDirectories, DebugDirectorySize)) {
  113. SetLastError( ERROR_BAD_EXE_FORMAT );
  114. goto nosyms;
  115. }
  116. NumberOfDebugDirectories = DebugDirectorySize / sizeof( IMAGE_DEBUG_DIRECTORY );
  117. SymbolFileHandle = CreateFile( pDbgFileName,
  118. GENERIC_READ | GENERIC_WRITE,
  119. FILE_SHARE_READ,
  120. NULL,
  121. OPEN_EXISTING,
  122. 0,
  123. NULL
  124. );
  125. if (SymbolFileHandle == INVALID_HANDLE_VALUE)
  126. goto nosyms;
  127. if (!ReadFile( SymbolFileHandle,
  128. &DbgFileHeader,
  129. sizeof(DbgFileHeader),
  130. &DebugDataSize,
  131. NULL) ||
  132. DebugDataSize != sizeof(DbgFileHeader)) {
  133. SetLastError( ERROR_BAD_EXE_FORMAT );
  134. goto nosyms;
  135. }
  136. if (DbgFileHeader.Signature != IMAGE_SEPARATE_DEBUG_SIGNATURE ||
  137. (DbgFileHeader.Flags & ~IMAGE_SEPARATE_DEBUG_FLAGS_MASK) != 0 ||
  138. DbgFileHeader.Machine != NtHeaders->FileHeader.Machine ||
  139. DbgFileHeader.Characteristics != NtHeaders->FileHeader.Characteristics ||
  140. DbgFileHeader.TimeDateStamp != NtHeaders->FileHeader.TimeDateStamp ||
  141. DbgFileHeader.CheckSum != NtHeaders->OptionalHeader.CheckSum ||
  142. DbgFileHeader.ImageBase != NtHeaders->OptionalHeader.ImageBase ||
  143. DbgFileHeader.SizeOfImage != NtHeaders->OptionalHeader.SizeOfImage) {
  144. SetLastError( ERROR_BAD_EXE_FORMAT );
  145. goto nosyms;
  146. }
  147. if (DbgFileHeader.Flags & IMAGE_SEPARATE_DEBUG_MISMATCH) {
  148. fprintf(stderr, "Warning: %s updated unsafely; symbols may be wrong\n",
  149. pDbgFileName);
  150. }
  151. // check if this is the right dbg file
  152. // save the DebugDirectory and get ready to write the
  153. // debug data to the image file.
  154. DebugDirectoriesSave = (PIMAGE_DEBUG_DIRECTORY) malloc( DebugDirectorySize );
  155. if (DebugDirectoriesSave == NULL)
  156. goto nosyms;
  157. RtlMoveMemory( DebugDirectoriesSave,
  158. DebugDirectories,
  159. DebugDirectorySize);
  160. DebugDirectory = DebugDirectoriesSave;
  161. NewFileSize = SetFilePointer( FileHandle, 0, NULL, FILE_END );
  162. NewFileSize = (NewFileSize + 3) & ~3;
  163. for (i=0; i<NumberOfDebugDirectories; i++) {
  164. // Is it one of the debug sections we need to special case?
  165. if (DebugDirectory->Type == IMAGE_DEBUG_TYPE_MISC) {
  166. // fix the mage name
  167. RtlCopyMemory(((PCHAR) ImageBase +
  168. DebugDirectory->PointerToRawData +
  169. FIELD_OFFSET( IMAGE_DEBUG_MISC, Data )),
  170. FilePart,
  171. strlen(FilePart) + 1);
  172. }
  173. else if (DebugDirectory->Type != IMAGE_DEBUG_TYPE_FPO) {
  174. DebugData = (LPBYTE) malloc( DebugDirectory->SizeOfData );
  175. if (SetFilePointer( SymbolFileHandle,
  176. DebugDirectory->PointerToRawData,
  177. NULL,
  178. FILE_BEGIN ) != DebugDirectory->PointerToRawData) {
  179. SetLastError( ERROR_BAD_EXE_FORMAT );
  180. goto nosyms;
  181. }
  182. if (ReadFile( SymbolFileHandle,
  183. DebugData,
  184. DebugDirectory->SizeOfData,
  185. &DebugDataSize,
  186. NULL) &&
  187. DebugDataSize == DebugDirectory->SizeOfData) {
  188. if (WriteFile( FileHandle,
  189. DebugData,
  190. DebugDirectory->SizeOfData,
  191. &DebugDataSize,
  192. NULL) &&
  193. DebugDataSize == DebugDirectory->SizeOfData) {
  194. DebugDirectory->PointerToRawData = NewFileSize;
  195. NewFileSize += DebugDataSize;
  196. NewFileSize = (NewFileSize + 3) & ~3;
  197. }
  198. else {
  199. SetLastError( ERROR_WRITE_FAULT );
  200. free( DebugData );
  201. goto nosyms;
  202. }
  203. }
  204. else {
  205. SetLastError( ERROR_BAD_EXE_FORMAT );
  206. free( DebugData );
  207. goto nosyms;
  208. }
  209. free( DebugData );
  210. }
  211. DebugDirectory += 1;
  212. }
  213. // somehow I needed to close the file and re-open it again.
  214. // otherwise it would AV inside CheckSumMappedFile.
  215. UnmapViewOfFile( ImageBase );
  216. CloseHandle( hMappedFile );
  217. ImageBase = NULL;
  218. hMappedFile = 0;
  219. SetFilePointer( FileHandle, NewFileSize, NULL, FILE_BEGIN );
  220. SetEndOfFile( FileHandle );
  221. CloseHandle( FileHandle );
  222. //
  223. // re-open and map the file.
  224. //
  225. FileHandle = CreateFile( pImageName,
  226. GENERIC_READ | GENERIC_WRITE,
  227. FILE_SHARE_READ,
  228. NULL,
  229. OPEN_EXISTING,
  230. 0,
  231. NULL
  232. );
  233. hMappedFile = CreateFileMapping( FileHandle,
  234. NULL,
  235. PAGE_READWRITE,
  236. 0,
  237. 0,
  238. NULL
  239. );
  240. if (!hMappedFile) {
  241. goto nosyms;
  242. }
  243. ImageBase = MapViewOfFile( hMappedFile,
  244. FILE_MAP_WRITE,
  245. 0,
  246. 0,
  247. 0
  248. );
  249. if (!ImageBase) {
  250. goto nosyms;
  251. }
  252. NtHeaders = ImageNtHeader( ImageBase );
  253. if (NtHeaders == NULL) {
  254. SetLastError( ERROR_BAD_EXE_FORMAT );
  255. goto nosyms;
  256. }
  257. DebugDirectories = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryEntryToData( ImageBase,
  258. FALSE,
  259. IMAGE_DIRECTORY_ENTRY_DEBUG,
  260. &DebugDirectorySize
  261. );
  262. if (DebugDirectories == NULL || DebugDirectorySize == 0) {
  263. SetLastError( ERROR_BAD_EXE_FORMAT );
  264. goto nosyms;
  265. }
  266. RtlMoveMemory( DebugDirectories,
  267. DebugDirectoriesSave,
  268. DebugDirectorySize);
  269. free( DebugDirectoriesSave );
  270. NtHeaders->FileHeader.Characteristics &= ~IMAGE_FILE_DEBUG_STRIPPED;
  271. CheckSumMappedFile( ImageBase,
  272. NewFileSize,
  273. &HeaderSum,
  274. &CheckSum
  275. );
  276. NtHeaders->OptionalHeader.CheckSum = CheckSum;
  277. CloseHandle( SymbolFileHandle );
  278. UnmapViewOfFile( ImageBase );
  279. CloseHandle( hMappedFile );
  280. CloseHandle( FileHandle );
  281. return TRUE;
  282. nosyms:
  283. SavedErrorCode = GetLastError();
  284. if (DebugDirectoriesSave)
  285. free( DebugDirectoriesSave );
  286. if (SymbolFileHandle && SymbolFileHandle != INVALID_HANDLE_VALUE) {
  287. CloseHandle( SymbolFileHandle );
  288. }
  289. if (ImageBase)
  290. UnmapViewOfFile( ImageBase );
  291. if (hMappedFile)
  292. CloseHandle( hMappedFile );
  293. if (FileHandle && FileHandle != INVALID_HANDLE_VALUE) {
  294. CloseHandle( FileHandle );
  295. }
  296. SetLastError( SavedErrorCode );
  297. return FALSE;
  298. }
  299. int __cdecl
  300. main(
  301. int argc,
  302. char *argv[],
  303. char *envp[]
  304. )
  305. {
  306. char c, *s;
  307. LPSTR DbgFilePart;
  308. if (argc <= 1) {
  309. Usage();
  310. }
  311. DbgFileName[ 0 ] = '\0';
  312. while (--argc) {
  313. s = *++argv;
  314. if (*s == '/' || *s == '-') {
  315. while (c = *++s)
  316. switch (toupper( c )) {
  317. case '?':
  318. Usage();
  319. break;
  320. case 'V':
  321. fVerbose = TRUE;
  322. break;
  323. case 'S':
  324. if (--argc) {
  325. strcpy( (PCHAR) DbgFileName, *++argv );
  326. }
  327. else {
  328. fprintf( stderr, "EDITSYM: Argument to /%c switch missing\n", c );
  329. Usage();
  330. }
  331. break;
  332. default:
  333. fprintf( stderr, "EDITSYM: Invalid switch - /%c\n", c );
  334. Usage();
  335. break;
  336. }
  337. }
  338. else {
  339. FilePart = (PCHAR) CurrentImageName;
  340. if (!GetFullPathNameA( s, sizeof( CurrentImageName ), (PCHAR) CurrentImageName, &FilePart )) {
  341. fprintf( stderr, "EDITSYM: invalid file name - %s (%u)\n", s, GetLastError() );
  342. }
  343. else {
  344. if (DbgFileName[0] == '\0') {
  345. PCHAR pDbgName;
  346. RtlCopyMemory(DbgFileName,
  347. CurrentImageName,
  348. strlen((PCHAR) CurrentImageName) + 1);
  349. pDbgName = (PCHAR) DbgFileName + strlen ((PCHAR) DbgFileName);
  350. while (pDbgName > (PCHAR) DbgFileName) {
  351. if (*pDbgName == '.') {
  352. break;
  353. }
  354. pDbgName --;
  355. }
  356. if (*pDbgName != '.') {
  357. fprintf( stderr, "EDITSYM: invalid exe file name - %s\n", CurrentImageName );
  358. }
  359. strcpy (pDbgName, ".DBG");
  360. }
  361. else if (!GetFullPathNameA( (PCHAR) DbgFileName, sizeof( DbgFileName ), (PCHAR) DbgFileName, &DbgFilePart )) {
  362. fprintf( stderr, "EDITSYM: invalid Dbg file name - %s (%u)\n", s, GetLastError() );
  363. }
  364. if (EditSymbols( (PCHAR) CurrentImageName, (PCHAR) DbgFileName )) {
  365. if (fVerbose) {
  366. fprintf( stdout,
  367. "EDITSYM: %s symbols restored into %s\n",
  368. DbgFileName,
  369. FilePart
  370. );
  371. }
  372. }
  373. else
  374. fprintf( stderr, "EDITSYM: Unable to restore symbols from '%s' into '%s' (%u)\n",
  375. CurrentImageName,
  376. DbgFileName,
  377. GetLastError()
  378. );
  379. }
  380. }
  381. }
  382. exit( 0 );
  383. return 0;
  384. }