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.

1206 lines
50 KiB

  1. #include <private.h>
  2. #if defined(use_SplitSymbolsX)
  3. # include <splitsymx.h>
  4. # define SymMalloc(a) malloc(a)
  5. # define SymFree(a) { if (a != NULL) { free(a); a=NULL; } }
  6. #else
  7. # define SymMalloc(a) MemAlloc(a)
  8. # define SymFree(a) { if (a != NULL) { MemFree(a); a=NULL; } }
  9. #endif // use_SplitSymbolsX
  10. #include <strsafe.h>
  11. #define CLEAN_PD(addr) ((addr) & ~0x3)
  12. #define CLEAN_PD64(addr) ((addr) & ~0x3UI64)
  13. #if defined(use_SplitSymbolsX)
  14. BOOL
  15. SplitSymbolsX(
  16. LPSTR ImageName,
  17. LPSTR SymbolsPath,
  18. LPSTR SymbolFilePath,
  19. DWORD SizeOfSymbolFilePath,
  20. ULONG Flags,
  21. PCHAR RSDSDllToLoad,
  22. LPSTR CreatedPdb,
  23. DWORD SizeOfPdbBuffer
  24. )
  25. #else
  26. BOOL
  27. IMAGEAPI
  28. SplitSymbols(
  29. LPSTR ImageName,
  30. LPSTR SymbolsPath,
  31. LPSTR SymbolFilePath,
  32. ULONG Flags
  33. )
  34. #endif // use_SplitSymbolsX
  35. {
  36. // UnSafe...
  37. HANDLE FileHandle = INVALID_HANDLE_VALUE, SymbolFileHandle = INVALID_HANDLE_VALUE;
  38. HANDLE hMappedFile;
  39. LPVOID ImageBase = NULL;
  40. PIMAGE_NT_HEADERS32 NtHeaders;
  41. LPSTR ImageFileName;
  42. DWORD SizeOfSymbols;
  43. ULONG_PTR ImageNameOffset;
  44. ULONG_PTR DebugSectionStart;
  45. PIMAGE_SECTION_HEADER DebugSection = NULL;
  46. DWORD SectionNumber, BytesWritten, NewFileSize, HeaderSum, CheckSum;
  47. PIMAGE_DEBUG_DIRECTORY DebugDirectory, DebugDirectories, DbgDebugDirectories = NULL;
  48. IMAGE_DEBUG_DIRECTORY MiscDebugDirectory = {0};
  49. IMAGE_DEBUG_DIRECTORY FpoDebugDirectory = {0};
  50. IMAGE_DEBUG_DIRECTORY FunctionTableDir;
  51. PIMAGE_DEBUG_DIRECTORY pFpoDebugDirectory = NULL;
  52. DWORD DebugDirectorySize, DbgFileHeaderSize, NumberOfDebugDirectories;
  53. IMAGE_SEPARATE_DEBUG_HEADER DbgFileHeader;
  54. PIMAGE_EXPORT_DIRECTORY ExportDirectory;
  55. DWORD ExportedNamesSize;
  56. LPDWORD pp;
  57. LPSTR ExportedNames = NULL, Src, Dst;
  58. DWORD i, j, RvaOffset, ExportDirectorySize;
  59. PFPO_DATA FpoTable = NULL;
  60. DWORD FpoTableSize;
  61. PIMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY RuntimeFunctionTable, pSrc;
  62. DWORD RuntimeFunctionTableSize;
  63. PIMAGE_FUNCTION_ENTRY FunctionTable = NULL, pDst;
  64. DWORD FunctionTableSize;
  65. ULONG NumberOfFunctionTableEntries, DbgOffset;
  66. DWORD SavedErrorCode;
  67. BOOL InsertExtensionSubDir;
  68. LPSTR ImageFilePathToSaveInImage;
  69. BOOL MiscInRdata = FALSE;
  70. BOOL DiscardFPO = Flags & SPLITSYM_EXTRACT_ALL;
  71. BOOL MiscDebugFound, OtherDebugFound, PdbDebugFound;
  72. BOOL fNewCvData = FALSE;
  73. PCHAR NewDebugData = NULL;
  74. CHAR AltPdbPath[_MAX_PATH+1];
  75. PIMAGE_FILE_HEADER FileHeader;
  76. PIMAGE_OPTIONAL_HEADER32 OptionalHeader;
  77. PIMAGE_SECTION_HEADER Sections;
  78. PCVDD pDebugCV;
  79. #if !defined(use_SplitSymbolsX) // SplitSymbolsX recieves this as a param
  80. DWORD SizeOfSymbolFilePath = MAX_PATH+1; // size of SymbolFilePath is assumed
  81. #endif
  82. LPSTR tempPtr;
  83. HRESULT hrRetCode;
  84. BOOL bSplitSymRetValue = FALSE; // by default, assume failure
  85. DWORD dwLastError = 0;
  86. __try { // SymbolsPath is manipulated within this function, but the size of the string
  87. // is not known so wrap everything in order to catch possible exceptions.
  88. // I still need to verify if this can possibly lead to leaked resources.
  89. //
  90. // verify the two required parameters are not NULL
  91. //
  92. if (ImageName==NULL || SymbolFilePath==NULL) {
  93. dwLastError = ERROR_INVALID_PARAMETER;
  94. __leave;
  95. }
  96. if (Flags & SPLITSYM_SYMBOLPATH_IS_SRC) {
  97. if ( S_OK != (hrRetCode = StringCbCopy(AltPdbPath, sizeof(AltPdbPath), SymbolFilePath)) ) {
  98. dwLastError = hrRetCode;
  99. __leave;
  100. }
  101. }
  102. //
  103. // make ImageFileName point to the first char after the last directory in ImageName (first char of filename)
  104. //
  105. ImageFileName = ImageName + strlen( ImageName );
  106. while (ImageFileName > ImageName) {
  107. if (*ImageFileName == '\\' ||
  108. *ImageFileName == '/' ||
  109. *ImageFileName == ':' )
  110. {
  111. ImageFileName = CharNext(ImageFileName);
  112. break;
  113. } else {
  114. ImageFileName = CharPrev(ImageName, ImageFileName);
  115. }
  116. }
  117. //
  118. // Put the initial symbols path into SymbolFilePath
  119. //
  120. if (SymbolsPath == NULL ||
  121. SymbolsPath[ 0 ] == '\0' ||
  122. SymbolsPath[ 0 ] == '.' )
  123. {
  124. CHAR TempChar;
  125. //
  126. // copy everything except the filename from ImageName to SymbolFilePath
  127. //
  128. TempChar = *ImageFileName; // temporarily null terminate ImageName immediately prior to the
  129. *ImageFileName = '\0'; // filename
  130. if ( S_OK != (hrRetCode = StringCchCopy(SymbolFilePath, SizeOfSymbolFilePath, ImageName)) ) {
  131. dwLastError = hrRetCode;
  132. __leave;
  133. }
  134. *ImageFileName = TempChar; // replace the character we temporarily removed
  135. InsertExtensionSubDir = FALSE;
  136. } else {
  137. //
  138. // Use the provided SymbolsPath
  139. //
  140. if ( S_OK != (hrRetCode = StringCchCopy(SymbolFilePath, SizeOfSymbolFilePath, SymbolsPath)) ) {
  141. dwLastError = hrRetCode;
  142. __leave;
  143. }
  144. InsertExtensionSubDir = TRUE;
  145. }
  146. //
  147. // make sure SymbolFilePath ends in '\\' and that Dst points to the end of the string
  148. //
  149. Dst = SymbolFilePath + strlen( SymbolFilePath );
  150. tempPtr = CharPrev(SymbolFilePath, Dst); // clean up PreFast warning
  151. if (Dst > SymbolFilePath &&
  152. *tempPtr != '\\' &&
  153. *tempPtr != '/' &&
  154. *tempPtr != ':')
  155. {
  156. if ( S_OK != (hrRetCode = StringCchCat(SymbolFilePath, SizeOfSymbolFilePath, "\\")) ) {
  157. dwLastError = hrRetCode;
  158. __leave;
  159. }
  160. Dst++; // fix prefast warning
  161. }
  162. // ImageFilePathToSaveInImage points to the end of SymbolFilePath
  163. ImageFilePathToSaveInImage = Dst;
  164. //
  165. // If there is a filename extension and InsertExtensionSubDir is TRUE, copy the extension to SymbolFilePath
  166. // as a subdirectory
  167. //
  168. Src = strrchr( ImageFileName, '.' );
  169. if (Src != NULL && InsertExtensionSubDir) {
  170. Src++; // Skip past '.'
  171. if ( S_OK != (hrRetCode = StringCchCat(SymbolFilePath, SizeOfSymbolFilePath, Src)) ) {
  172. dwLastError = hrRetCode;
  173. __leave;
  174. }
  175. if ( S_OK != (hrRetCode = StringCchCat(SymbolFilePath, SizeOfSymbolFilePath, "\\")) ) {
  176. dwLastError = hrRetCode;
  177. __leave;
  178. }
  179. }
  180. //
  181. // add the filename to SymbolFilePath
  182. //
  183. if ( S_OK != (hrRetCode = StringCchCat(SymbolFilePath, SizeOfSymbolFilePath, ImageFileName)) ) {
  184. dwLastError = hrRetCode;
  185. __leave;
  186. }
  187. //
  188. // change the extension to ".dbg" (or just append ".dbg" ??)
  189. //
  190. Dst = strrchr(Dst, '.');
  191. if (Dst == NULL) {
  192. Dst = SymbolFilePath + strlen( SymbolFilePath );
  193. } else {
  194. *Dst = '\0';
  195. }
  196. if ( S_OK != (hrRetCode = StringCchCat( SymbolFilePath, SizeOfSymbolFilePath, ".dbg" )) ) {
  197. dwLastError = hrRetCode;
  198. __leave;
  199. }
  200. // Now, open and map the input file.
  201. FileHandle = CreateFile( ImageName,
  202. GENERIC_READ | GENERIC_WRITE,
  203. FILE_SHARE_READ,
  204. NULL,
  205. OPEN_EXISTING,
  206. 0,
  207. NULL
  208. );
  209. if (FileHandle == INVALID_HANDLE_VALUE) {
  210. __leave;
  211. }
  212. hMappedFile = CreateFileMapping( FileHandle,
  213. NULL,
  214. PAGE_READWRITE,
  215. 0,
  216. 0,
  217. NULL
  218. );
  219. if (!hMappedFile) {
  220. __leave;
  221. }
  222. ImageBase = MapViewOfFile( hMappedFile,
  223. FILE_MAP_WRITE,
  224. 0,
  225. 0,
  226. 0
  227. );
  228. CloseHandle( hMappedFile );
  229. if (!ImageBase) {
  230. __leave;
  231. }
  232. //
  233. // Everything is mapped. Now check the image and find nt image headers
  234. //
  235. #ifndef _WIN64
  236. NtHeaders = ImageNtHeader( ImageBase );
  237. if (NtHeaders == NULL) {
  238. FileHeader = (PIMAGE_FILE_HEADER)ImageBase;
  239. OptionalHeader = ((PIMAGE_OPTIONAL_HEADER32)((ULONG_PTR)FileHeader+IMAGE_SIZEOF_FILE_HEADER));
  240. // One last check
  241. if (OptionalHeader->Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
  242. goto HeaderOk;
  243. HeaderBad:
  244. #endif
  245. dwLastError = ERROR_BAD_EXE_FORMAT;
  246. __leave;
  247. #ifndef _WIN64
  248. } else {
  249. FileHeader = &NtHeaders->FileHeader;
  250. OptionalHeader = &NtHeaders->OptionalHeader;
  251. if (OptionalHeader->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
  252. goto HeaderBad;
  253. }
  254. HeaderOk:
  255. if ((OptionalHeader->MajorLinkerVersion < 3) &&
  256. (OptionalHeader->MinorLinkerVersion < 5) )
  257. {
  258. dwLastError = ERROR_BAD_EXE_FORMAT;
  259. __leave;
  260. }
  261. {
  262. DWORD dwDataSize;
  263. PVOID pData;
  264. pData = ImageDirectoryEntryToData(ImageBase, FALSE, IMAGE_DIRECTORY_ENTRY_SECURITY, &dwDataSize);
  265. if (pData || dwDataSize) {
  266. // This image has been signed. Can't strip the symbols w/o invalidating the certificate.
  267. dwLastError = ERROR_BAD_EXE_FORMAT;
  268. __leave;
  269. }
  270. pData = ImageDirectoryEntryToData(
  271. ImageBase,
  272. FALSE,
  273. IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
  274. &dwDataSize
  275. );
  276. if (pData) {
  277. // COR header found - see if it's strong signed
  278. if (((IMAGE_COR20_HEADER *)pData)->Flags & COMIMAGE_FLAGS_STRONGNAMESIGNED)
  279. {
  280. // This image has been strong signed. Can't strip the symbols w/o invalidating the certificate.
  281. dwLastError = ERROR_BAD_EXE_FORMAT;
  282. __leave;
  283. }
  284. }
  285. }
  286. if (FileHeader->Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
  287. {
  288. // The symbols have already been stripped. No need to continue.
  289. dwLastError = ERROR_ALREADY_ASSIGNED;
  290. __leave;
  291. }
  292. DebugDirectories = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryEntryToData( ImageBase,
  293. FALSE,
  294. IMAGE_DIRECTORY_ENTRY_DEBUG,
  295. &DebugDirectorySize
  296. );
  297. if (!DebugDirectoryIsUseful(DebugDirectories, DebugDirectorySize)) {
  298. dwLastError = ERROR_BAD_EXE_FORMAT;
  299. __leave;
  300. }
  301. NumberOfDebugDirectories = DebugDirectorySize / sizeof( IMAGE_DEBUG_DIRECTORY );
  302. // See if there's a MISC debug dir and if not, there s/b ONLY a CV data or it's an error.
  303. MiscDebugFound = FALSE;
  304. OtherDebugFound = FALSE;
  305. for (i=0,DebugDirectory=DebugDirectories; i<NumberOfDebugDirectories; i++,DebugDirectory++) {
  306. switch (DebugDirectory->Type) {
  307. case IMAGE_DEBUG_TYPE_MISC:
  308. MiscDebugFound = TRUE;
  309. break;
  310. case IMAGE_DEBUG_TYPE_CODEVIEW:
  311. pDebugCV = ( PCVDD ) (DebugDirectory->PointerToRawData + (PCHAR)ImageBase);
  312. if (pDebugCV->dwSig == '01BN') {
  313. PdbDebugFound = TRUE;
  314. }
  315. #if defined(use_SplitSymbolsX)
  316. if (pDebugCV->dwSig == 'SDSR') {
  317. PdbDebugFound = TRUE;
  318. }
  319. #endif
  320. break;
  321. default:
  322. OtherDebugFound = TRUE;
  323. break;
  324. }
  325. }
  326. if (OtherDebugFound && !MiscDebugFound) {
  327. dwLastError = ERROR_BAD_EXE_FORMAT;
  328. __leave;
  329. }
  330. if (PdbDebugFound && !OtherDebugFound && (OptionalHeader->MajorLinkerVersion >= 6)) {
  331. // This is a VC6 generated image. Don't create a .dbg file.
  332. MiscDebugFound = FALSE;
  333. }
  334. // Make sure we can open the .dbg file before we continue...
  335. if (!MakeSureDirectoryPathExists( SymbolFilePath )) {
  336. __leave;
  337. }
  338. if (MiscDebugFound) {
  339. // Try to open the symbol file
  340. SymbolFileHandle = CreateFile( SymbolFilePath,
  341. GENERIC_WRITE,
  342. 0,
  343. NULL,
  344. CREATE_ALWAYS,
  345. 0,
  346. NULL
  347. );
  348. if (SymbolFileHandle == INVALID_HANDLE_VALUE) {
  349. goto nosyms;
  350. }
  351. }
  352. // The entire file is mapped so we don't have to care if the rva's
  353. // are correct. It is interesting to note if there's a debug section
  354. // we need to whack before terminating, though.
  355. {
  356. if (NtHeaders) {
  357. Sections = IMAGE_FIRST_SECTION( NtHeaders );
  358. } else {
  359. Sections = (PIMAGE_SECTION_HEADER)
  360. ((ULONG_PTR)ImageBase +
  361. ((PIMAGE_FILE_HEADER)ImageBase)->SizeOfOptionalHeader +
  362. IMAGE_SIZEOF_FILE_HEADER );
  363. }
  364. for (SectionNumber = 0;
  365. SectionNumber < FileHeader->NumberOfSections;
  366. SectionNumber++ ) {
  367. if (Sections[ SectionNumber ].PointerToRawData != 0 &&
  368. !_stricmp( (char *) Sections[ SectionNumber ].Name, ".debug" )) {
  369. DebugSection = &Sections[ SectionNumber ];
  370. }
  371. }
  372. }
  373. FpoTable = NULL;
  374. ExportedNames = NULL;
  375. DebugSectionStart = 0xffffffff;
  376. //
  377. // Find the size of the debug section.
  378. //
  379. SizeOfSymbols = 0;
  380. for (i=0,DebugDirectory=DebugDirectories; i<NumberOfDebugDirectories; i++,DebugDirectory++) {
  381. switch (DebugDirectory->Type) {
  382. case IMAGE_DEBUG_TYPE_MISC :
  383. // Save it away.
  384. MiscDebugDirectory = *DebugDirectory;
  385. // check to see if the misc debug data is in some other section.
  386. // If Address Of Raw Data is cleared, it must be in .debug (there's no such thing as not-mapped rdata)
  387. // If it's set and there's no debug section, it must be somewhere else.
  388. // If it's set and there's a debug section, check the range.
  389. if ((DebugDirectory->AddressOfRawData != 0) &&
  390. ((DebugSection == NULL) ||
  391. (((DebugDirectory->PointerToRawData < DebugSection->PointerToRawData) ||
  392. (DebugDirectory->PointerToRawData >= DebugSection->PointerToRawData + DebugSection->SizeOfRawData)
  393. )
  394. )
  395. )
  396. )
  397. {
  398. MiscInRdata = TRUE;
  399. } else {
  400. if (DebugDirectory->PointerToRawData < DebugSectionStart) {
  401. DebugSectionStart = DebugDirectory->PointerToRawData;
  402. }
  403. }
  404. break;
  405. case IMAGE_DEBUG_TYPE_FPO:
  406. if (DebugDirectory->PointerToRawData < DebugSectionStart) {
  407. DebugSectionStart = DebugDirectory->PointerToRawData;
  408. }
  409. // Save it away.
  410. FpoDebugDirectory = *DebugDirectory;
  411. pFpoDebugDirectory = DebugDirectory;
  412. break;
  413. case IMAGE_DEBUG_TYPE_CODEVIEW:
  414. {
  415. ULONG NewDebugSize;
  416. if (DebugDirectory->PointerToRawData < DebugSectionStart) {
  417. DebugSectionStart = DebugDirectory->PointerToRawData;
  418. }
  419. // If private's are removed do so to the static CV data and save the new size...
  420. pDebugCV = ( PCVDD ) (DebugDirectory->PointerToRawData + (PCHAR)ImageBase);
  421. if (pDebugCV->dwSig == '01BN') {
  422. // Got a PDB. The name immediately follows the signature.
  423. CHAR PdbName[_MAX_PATH + 1];
  424. CHAR NewPdbName[_MAX_PATH + 1];
  425. CHAR Drive[_MAX_DRIVE + 1];
  426. CHAR Dir[_MAX_DIR + 1];
  427. CHAR Filename[_MAX_FNAME + 1];
  428. CHAR FileExt[_MAX_EXT + 1];
  429. BOOL rc;
  430. memset(PdbName, 0, sizeof(PdbName));
  431. memcpy(PdbName, ((PCHAR)pDebugCV)+ sizeof(NB10IH), DebugDirectory->SizeOfData - sizeof(NB10IH));
  432. _splitpath(PdbName, NULL, NULL, Filename, FileExt);
  433. _splitpath(SymbolFilePath, Drive, Dir, NULL, NULL);
  434. _makepath(NewPdbName, Drive, Dir, Filename, FileExt);
  435. #if defined(use_SplitSymbolsX)
  436. rc = CopyPdbX(PdbName, NewPdbName, Flags & SPLITSYM_REMOVE_PRIVATE, NULL);
  437. if (rc) {
  438. StringCchCopy(CreatedPdb, SizeOfPdbBuffer, NewPdbName);
  439. }
  440. #else
  441. rc = CopyPdb(PdbName, NewPdbName, Flags & SPLITSYM_REMOVE_PRIVATE);
  442. #endif
  443. if (!rc) {
  444. if (Flags & SPLITSYM_SYMBOLPATH_IS_SRC) {
  445. // Try the AltPdbPath.
  446. if ( S_OK != (hrRetCode = StringCbCopy(PdbName, sizeof(PdbName), AltPdbPath)) ) {
  447. dwLastError = hrRetCode;
  448. __leave;
  449. }
  450. if ( S_OK != (hrRetCode = StringCbCat( PdbName, sizeof(PdbName), Filename)) ) {
  451. dwLastError = hrRetCode;
  452. __leave;
  453. }
  454. if ( S_OK != (hrRetCode = StringCbCat( PdbName, sizeof(PdbName), FileExt)) ) {
  455. dwLastError = hrRetCode;
  456. __leave;
  457. }
  458. #if defined(use_SplitSymbolsX)
  459. rc = CopyPdbX(PdbName, NewPdbName, Flags & SPLITSYM_REMOVE_PRIVATE, NULL);
  460. if (rc) {
  461. StringCchCopy(CreatedPdb, SizeOfPdbBuffer, NewPdbName);
  462. }
  463. #else
  464. rc = CopyPdb(PdbName, NewPdbName, Flags & SPLITSYM_REMOVE_PRIVATE);
  465. #endif
  466. }
  467. if ( !rc) {
  468. // It's possible the name in the pdb isn't in the same location as it was when built. See if we can
  469. // find it in the same dir as the image...
  470. _splitpath(ImageName, Drive, Dir, NULL, NULL);
  471. _makepath(PdbName, Drive, Dir, Filename, FileExt);
  472. #if defined(use_SplitSymbolsX)
  473. rc = CopyPdbX(PdbName, NewPdbName, Flags & SPLITSYM_REMOVE_PRIVATE, NULL);
  474. if (rc) {
  475. StringCchCopy(CreatedPdb, SizeOfPdbBuffer, NewPdbName);
  476. }
  477. #else
  478. rc = CopyPdb(PdbName, NewPdbName, Flags & SPLITSYM_REMOVE_PRIVATE);
  479. #endif
  480. }
  481. }
  482. if (rc) {
  483. SetFileAttributes(NewPdbName, FILE_ATTRIBUTE_NORMAL);
  484. // Change the data so only the pdb name is in the .dbg file (no path).
  485. if (MiscDebugFound) {
  486. NewDebugSize = sizeof(NB10IH) + strlen(Filename) + strlen(FileExt) + 1;
  487. NewDebugData = (PCHAR) SymMalloc( NewDebugSize );
  488. ((PCVDD)NewDebugData)->nb10ih = pDebugCV->nb10ih;
  489. if ( S_OK != (hrRetCode = StringCbCopy(NewDebugData + sizeof(NB10IH), NewDebugSize-sizeof(NB10IH), Filename)) ) {
  490. dwLastError = hrRetCode;
  491. __leave;
  492. }
  493. if ( S_OK != (hrRetCode = StringCbCat( NewDebugData + sizeof(NB10IH), NewDebugSize-sizeof(NB10IH), FileExt)) ) {
  494. dwLastError = hrRetCode;
  495. __leave;
  496. }
  497. DebugDirectory->PointerToRawData = (ULONG) (NewDebugData - (PCHAR)ImageBase);
  498. DebugDirectory->SizeOfData = NewDebugSize;
  499. } else {
  500. if ( S_OK != (hrRetCode = StringCbCopy( ((PCHAR)pDebugCV) + sizeof(NB10IH), DebugDirectory->SizeOfData - sizeof(NB10IH), Filename)) ) {
  501. dwLastError = hrRetCode;
  502. __leave;
  503. }
  504. if ( S_OK != (hrRetCode = StringCbCat( ((PCHAR)pDebugCV)+ sizeof(NB10IH), DebugDirectory->SizeOfData - sizeof(NB10IH), FileExt)) ) {
  505. dwLastError = hrRetCode;
  506. __leave;
  507. }
  508. }
  509. } else {
  510. // Replace <Path>\<filename>.<ext> with just <filename>.<ext> in the debug data
  511. if ( S_OK != (hrRetCode = StringCbCopy(((PCHAR)pDebugCV) + sizeof(NB10IH), DebugDirectory->SizeOfData - sizeof(NB10IH), Filename)) ) {
  512. dwLastError = hrRetCode;
  513. __leave;
  514. }
  515. if ( S_OK != (hrRetCode = StringCbCat( ((PCHAR)pDebugCV) + sizeof(NB10IH), DebugDirectory->SizeOfData - sizeof(NB10IH), FileExt)) ) {
  516. dwLastError = hrRetCode;
  517. __leave;
  518. }
  519. DebugDirectory->SizeOfData = sizeof(NB10IH) + strlen(Filename) + strlen(FileExt) + 1;
  520. }
  521. #if defined(use_SplitSymbolsX)
  522. } else if ( pDebugCV->dwSig == 'SDSR') {
  523. // Got a PDB. The name immediately follows the signature.
  524. CHAR PdbName[sizeof(((PRSDSI)(0))->szPdb)];
  525. CHAR NewPdbName[_MAX_PATH+1];
  526. CHAR Drive[_MAX_DRIVE+1];
  527. CHAR Dir[_MAX_DIR+1];
  528. CHAR Filename[_MAX_FNAME+1];
  529. CHAR FileExt[_MAX_EXT+1];
  530. BOOL rc;
  531. ZeroMemory(PdbName, sizeof(PdbName));
  532. memcpy(PdbName, ((PCHAR)pDebugCV)+ sizeof(RSDSIH), __min(DebugDirectory->SizeOfData - sizeof(RSDSIH), sizeof(PdbName)));
  533. _splitpath(PdbName, NULL, NULL, Filename, FileExt);
  534. _splitpath(SymbolFilePath, Drive, Dir, NULL, NULL);
  535. _makepath(NewPdbName, Drive, Dir, Filename, FileExt);
  536. rc = CopyPdbX(PdbName, NewPdbName, Flags & SPLITSYM_REMOVE_PRIVATE, RSDSDllToLoad);
  537. if (rc) {
  538. StringCchCopy(CreatedPdb, SizeOfPdbBuffer, NewPdbName);
  539. }
  540. if (!rc) {
  541. if (Flags & SPLITSYM_SYMBOLPATH_IS_SRC) {
  542. // Try the AltPdbPath.
  543. if ( S_OK != (hrRetCode = StringCbCopy(PdbName, sizeof(PdbName), AltPdbPath)) ) {
  544. dwLastError = hrRetCode;
  545. __leave;
  546. }
  547. if ( S_OK != (hrRetCode = StringCbCat( PdbName, sizeof(PdbName), Filename)) ) {
  548. dwLastError = hrRetCode;
  549. __leave;
  550. }
  551. if ( S_OK != (hrRetCode = StringCbCat( PdbName, sizeof(PdbName), FileExt)) ) {
  552. dwLastError = hrRetCode;
  553. __leave;
  554. }
  555. rc = CopyPdbX(PdbName, NewPdbName, Flags & SPLITSYM_REMOVE_PRIVATE, RSDSDllToLoad);
  556. if (rc) {
  557. StringCchCopy(CreatedPdb, SizeOfPdbBuffer, NewPdbName);
  558. }
  559. }
  560. if ( !rc) {
  561. // It's possible the name in the pdb isn't in the same location as it was when built. See if we can
  562. // find it in the same dir as the image...
  563. _splitpath(ImageName, Drive, Dir, NULL, NULL);
  564. _makepath(PdbName, Drive, Dir, Filename, FileExt);
  565. rc = CopyPdbX(PdbName, NewPdbName, Flags & SPLITSYM_REMOVE_PRIVATE, RSDSDllToLoad);
  566. if (rc) {
  567. StringCchCopy(CreatedPdb, SizeOfPdbBuffer, NewPdbName);
  568. }
  569. }
  570. }
  571. if (rc) {
  572. SetFileAttributes(NewPdbName, FILE_ATTRIBUTE_NORMAL);
  573. // Change the data so only the pdb name is in the .dbg file (no path).
  574. if (MiscDebugFound) {
  575. NewDebugSize = sizeof(RSDSIH) + strlen(Filename) + strlen(FileExt) + 1;
  576. NewDebugData = (PCHAR) SymMalloc( NewDebugSize );
  577. ((PCVDD)NewDebugData)->rsdsih = pDebugCV->rsdsih;
  578. if ( S_OK != (hrRetCode = StringCbCopy(NewDebugData + sizeof(RSDSIH), NewDebugSize-sizeof(RSDSIH), Filename)) ) {
  579. dwLastError = hrRetCode;
  580. __leave;
  581. }
  582. if ( S_OK != (hrRetCode = StringCbCat( NewDebugData + sizeof(RSDSIH), NewDebugSize-sizeof(RSDSIH), FileExt)) ) {
  583. dwLastError = hrRetCode;
  584. __leave;
  585. }
  586. DebugDirectory->PointerToRawData = (ULONG) (NewDebugData - (PCHAR)ImageBase);
  587. DebugDirectory->SizeOfData = NewDebugSize;
  588. } else {
  589. if ( S_OK != (hrRetCode = StringCbCopy(((PCHAR)pDebugCV) + sizeof(RSDSIH), DebugDirectory->SizeOfData - sizeof(RSDSIH), Filename)) ) {
  590. dwLastError = hrRetCode;
  591. __leave;
  592. }
  593. if ( S_OK != (hrRetCode = StringCbCat( ((PCHAR)pDebugCV) + sizeof(RSDSIH), DebugDirectory->SizeOfData - sizeof(RSDSIH), FileExt)) ) {
  594. dwLastError = hrRetCode;
  595. __leave;
  596. }
  597. }
  598. } else {
  599. // Replace <Path>\<filename>.<ext> with just <filename>.<ext> in the debug data
  600. if ( S_OK != (hrRetCode = StringCbCopy(((PCHAR)pDebugCV) + sizeof(RSDSIH), DebugDirectory->SizeOfData - sizeof(RSDSIH), Filename)) ) {
  601. dwLastError = hrRetCode;
  602. __leave;
  603. }
  604. if ( S_OK != (hrRetCode = StringCbCat( ((PCHAR)pDebugCV) + sizeof(RSDSIH), DebugDirectory->SizeOfData - sizeof(RSDSIH), FileExt)) ) {
  605. dwLastError = hrRetCode;
  606. __leave;
  607. }
  608. DebugDirectory->SizeOfData = sizeof(RSDSIH) + strlen(Filename) + strlen(FileExt) + 1;
  609. }
  610. #endif
  611. } else {
  612. if (Flags & SPLITSYM_REMOVE_PRIVATE) {
  613. if (RemovePrivateCvSymbolicEx(DebugDirectory->PointerToRawData + (PCHAR)ImageBase,
  614. DebugDirectory->SizeOfData,
  615. &NewDebugData,
  616. &NewDebugSize)) {
  617. if (DebugDirectory->PointerToRawData != (ULONG) (NewDebugData - (PCHAR)ImageBase))
  618. {
  619. DebugDirectory->PointerToRawData = (ULONG) (NewDebugData - (PCHAR)ImageBase);
  620. DebugDirectory->SizeOfData = NewDebugSize;
  621. } else {
  622. NewDebugData = NULL;
  623. }
  624. }
  625. }
  626. }
  627. }
  628. break;
  629. case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  630. case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  631. if (DebugDirectory->PointerToRawData < DebugSectionStart) {
  632. DebugSectionStart = DebugDirectory->PointerToRawData;
  633. }
  634. // W/o the OMAP, FPO is useless.
  635. DiscardFPO = TRUE;
  636. break;
  637. case IMAGE_DEBUG_TYPE_FIXUP:
  638. if (DebugDirectory->PointerToRawData < DebugSectionStart) {
  639. DebugSectionStart = DebugDirectory->PointerToRawData;
  640. }
  641. // If all PRIVATE debug is removed, don't send FIXUP along.
  642. if (Flags & SPLITSYM_REMOVE_PRIVATE) {
  643. DebugDirectory->SizeOfData = 0;
  644. }
  645. break;
  646. default:
  647. if (DebugDirectory->SizeOfData &&
  648. (DebugDirectory->PointerToRawData < DebugSectionStart))
  649. {
  650. DebugSectionStart = DebugDirectory->PointerToRawData;
  651. }
  652. // Nothing else to special case...
  653. break;
  654. }
  655. SizeOfSymbols += (DebugDirectory->SizeOfData + 3) & ~3; // Minimally align it all.
  656. }
  657. if (!MiscDebugFound) {
  658. NewFileSize = GetFileSize(FileHandle, NULL);
  659. CheckSumMappedFile( ImageBase,
  660. NewFileSize,
  661. &HeaderSum,
  662. &CheckSum
  663. );
  664. OptionalHeader->CheckSum = CheckSum;
  665. goto nomisc;
  666. }
  667. if (DiscardFPO) {
  668. pFpoDebugDirectory = NULL;
  669. }
  670. if (pFpoDebugDirectory) {
  671. // If FPO stays here, make a copy so we don't need to worry about stomping on it.
  672. FpoTableSize = pFpoDebugDirectory->SizeOfData;
  673. FpoTable = (PFPO_DATA) SymMalloc( FpoTableSize );
  674. if ( FpoTable == NULL ) {
  675. goto nosyms;
  676. }
  677. RtlMoveMemory( FpoTable,
  678. (PCHAR) ImageBase + pFpoDebugDirectory->PointerToRawData,
  679. FpoTableSize );
  680. }
  681. ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
  682. ImageDirectoryEntryToData( ImageBase,
  683. FALSE,
  684. IMAGE_DIRECTORY_ENTRY_EXPORT,
  685. &ExportDirectorySize
  686. );
  687. if (ExportDirectory) {
  688. //
  689. // This particular piece of magic gets us the RVA of the
  690. // EXPORT section. Dont ask.
  691. //
  692. RvaOffset = (ULONG_PTR)
  693. ImageDirectoryEntryToData( ImageBase,
  694. TRUE,
  695. IMAGE_DIRECTORY_ENTRY_EXPORT,
  696. &ExportDirectorySize
  697. ) - (ULONG_PTR)ImageBase;
  698. pp = (LPDWORD)((ULONG_PTR)ExportDirectory +
  699. (ULONG_PTR)ExportDirectory->AddressOfNames - RvaOffset
  700. );
  701. ExportedNamesSize = 1;
  702. for (i=0; i<ExportDirectory->NumberOfNames; i++) {
  703. Src = (LPSTR)((ULONG_PTR)ExportDirectory + *pp++ - RvaOffset);
  704. ExportedNamesSize += strlen( Src ) + 1;
  705. }
  706. ExportedNamesSize = (ExportedNamesSize + 16) & ~15;
  707. Dst = (LPSTR) SymMalloc( ExportedNamesSize );
  708. if (Dst != NULL) {
  709. ExportedNames = Dst;
  710. pp = (LPDWORD)((ULONG_PTR)ExportDirectory +
  711. (ULONG_PTR)ExportDirectory->AddressOfNames - RvaOffset
  712. );
  713. for (i=0; i<ExportDirectory->NumberOfNames; i++) {
  714. Src = (LPSTR)((ULONG_PTR)ExportDirectory + *pp++ - RvaOffset);
  715. while (*Dst++ = *Src++) {
  716. ;
  717. }
  718. }
  719. }
  720. } else {
  721. ExportedNamesSize = 0;
  722. }
  723. RuntimeFunctionTable = (PIMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY)
  724. ImageDirectoryEntryToData( ImageBase,
  725. FALSE,
  726. IMAGE_DIRECTORY_ENTRY_EXCEPTION,
  727. &RuntimeFunctionTableSize
  728. );
  729. if (RuntimeFunctionTable == NULL) {
  730. RuntimeFunctionTableSize = 0;
  731. FunctionTableSize = 0;
  732. FunctionTable = NULL;
  733. }
  734. else {
  735. NumberOfFunctionTableEntries = RuntimeFunctionTableSize / sizeof( IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY );
  736. FunctionTableSize = NumberOfFunctionTableEntries * sizeof( IMAGE_FUNCTION_ENTRY );
  737. FunctionTable = (PIMAGE_FUNCTION_ENTRY) SymMalloc( FunctionTableSize );
  738. if (FunctionTable == NULL) {
  739. goto nosyms;
  740. }
  741. pSrc = RuntimeFunctionTable;
  742. pDst = FunctionTable;
  743. for (i=0; i<NumberOfFunctionTableEntries; i++) {
  744. //
  745. // Make .pdata entries in .DBG file relative.
  746. //
  747. pDst->StartingAddress = CLEAN_PD(pSrc->BeginAddress) - OptionalHeader->ImageBase;
  748. pDst->EndingAddress = CLEAN_PD(pSrc->EndAddress) - OptionalHeader->ImageBase;
  749. pDst->EndOfPrologue = CLEAN_PD(pSrc->PrologEndAddress) - OptionalHeader->ImageBase;
  750. pSrc += 1;
  751. pDst += 1;
  752. }
  753. }
  754. DbgFileHeaderSize = sizeof( DbgFileHeader ) +
  755. ((FileHeader->NumberOfSections - (DebugSection ? 1 : 0)) *
  756. sizeof( IMAGE_SECTION_HEADER )) +
  757. ExportedNamesSize +
  758. FunctionTableSize +
  759. DebugDirectorySize;
  760. if (FunctionTable != NULL) {
  761. DbgFileHeaderSize += sizeof( IMAGE_DEBUG_DIRECTORY );
  762. memset( &FunctionTableDir, 0, sizeof( IMAGE_DEBUG_DIRECTORY ) );
  763. FunctionTableDir.Type = IMAGE_DEBUG_TYPE_EXCEPTION;
  764. FunctionTableDir.SizeOfData = FunctionTableSize;
  765. FunctionTableDir.PointerToRawData = DbgFileHeaderSize - FunctionTableSize;
  766. }
  767. DbgFileHeaderSize = ((DbgFileHeaderSize + 15) & ~15);
  768. BytesWritten = 0;
  769. if (SetFilePointer( SymbolFileHandle,
  770. DbgFileHeaderSize,
  771. NULL,
  772. FILE_BEGIN
  773. ) == DbgFileHeaderSize ) {
  774. for (i=0, DebugDirectory=DebugDirectories;
  775. i < NumberOfDebugDirectories;
  776. i++, DebugDirectory++) {
  777. DWORD WriteCount;
  778. if (DebugDirectory->SizeOfData) {
  779. WriteFile( SymbolFileHandle,
  780. (PCHAR) ImageBase + DebugDirectory->PointerToRawData,
  781. (DebugDirectory->SizeOfData +3) & ~3,
  782. &WriteCount,
  783. NULL );
  784. BytesWritten += WriteCount;
  785. }
  786. }
  787. }
  788. if (BytesWritten == SizeOfSymbols) {
  789. FileHeader->PointerToSymbolTable = 0;
  790. FileHeader->NumberOfSymbols = 0;
  791. FileHeader->Characteristics |= IMAGE_FILE_DEBUG_STRIPPED;
  792. if (DebugSection != NULL) {
  793. OptionalHeader->SizeOfImage = DebugSection->VirtualAddress;
  794. OptionalHeader->SizeOfInitializedData -= DebugSection->SizeOfRawData;
  795. FileHeader->NumberOfSections--;
  796. // NULL out that section
  797. memset(DebugSection, 0, IMAGE_SIZEOF_SECTION_HEADER);
  798. }
  799. NewFileSize = DebugSectionStart; // Start with no symbolic
  800. //
  801. // Now that the data has moved to the .dbg file, rebuild the original
  802. // with MISC debug first and FPO second.
  803. //
  804. if (MiscDebugDirectory.SizeOfData) {
  805. if (MiscInRdata) {
  806. // Just store the new name in the existing misc field...
  807. ImageNameOffset = (ULONG_PTR) ((PCHAR)ImageBase +
  808. MiscDebugDirectory.PointerToRawData +
  809. FIELD_OFFSET( IMAGE_DEBUG_MISC, Data ));
  810. RtlCopyMemory( (LPVOID) ImageNameOffset,
  811. ImageFilePathToSaveInImage,
  812. strlen(ImageFilePathToSaveInImage) + 1 );
  813. } else {
  814. if (DebugSectionStart != MiscDebugDirectory.PointerToRawData) {
  815. RtlMoveMemory((PCHAR) ImageBase + DebugSectionStart,
  816. (PCHAR) ImageBase + MiscDebugDirectory.PointerToRawData,
  817. MiscDebugDirectory.SizeOfData);
  818. }
  819. ImageNameOffset = (ULONG_PTR) ((PCHAR)ImageBase + DebugSectionStart +
  820. FIELD_OFFSET( IMAGE_DEBUG_MISC, Data ));
  821. RtlCopyMemory( (LPVOID)ImageNameOffset,
  822. ImageFilePathToSaveInImage,
  823. strlen(ImageFilePathToSaveInImage) + 1 );
  824. NewFileSize += MiscDebugDirectory.SizeOfData;
  825. NewFileSize = (NewFileSize + 3) & ~3;
  826. }
  827. }
  828. if (FpoTable) {
  829. RtlCopyMemory( (PCHAR) ImageBase + NewFileSize,
  830. FpoTable,
  831. FpoTableSize );
  832. NewFileSize += FpoTableSize;
  833. NewFileSize = (NewFileSize + 3) & ~3;
  834. }
  835. // Make a copy of the Debug directory that we can write into the .dbg file
  836. DbgDebugDirectories = (PIMAGE_DEBUG_DIRECTORY) SymMalloc( NumberOfDebugDirectories * sizeof(IMAGE_DEBUG_DIRECTORY) );
  837. RtlMoveMemory(DbgDebugDirectories,
  838. DebugDirectories,
  839. sizeof(IMAGE_DEBUG_DIRECTORY) * NumberOfDebugDirectories);
  840. // Then write the MISC and (perhaps) FPO data to the image.
  841. FpoDebugDirectory.PointerToRawData = DebugSectionStart;
  842. DebugDirectorySize = 0;
  843. if (MiscDebugDirectory.SizeOfData != 0) {
  844. if (!MiscInRdata) {
  845. MiscDebugDirectory.PointerToRawData = DebugSectionStart;
  846. FpoDebugDirectory.PointerToRawData += MiscDebugDirectory.SizeOfData;
  847. MiscDebugDirectory.AddressOfRawData = 0;
  848. }
  849. DebugDirectories[0] = MiscDebugDirectory;
  850. DebugDirectorySize += sizeof(IMAGE_DEBUG_DIRECTORY);
  851. }
  852. if (pFpoDebugDirectory) {
  853. FpoDebugDirectory.AddressOfRawData = 0;
  854. DebugDirectories[DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY)] = FpoDebugDirectory;
  855. DebugDirectorySize += sizeof(IMAGE_DEBUG_DIRECTORY);
  856. }
  857. // Zero out remaining slots in image.
  858. if (NumberOfDebugDirectories < (DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY))) {
  859. ZeroMemory(&DebugDirectories[DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY)],
  860. NumberOfDebugDirectories * sizeof(IMAGE_DEBUG_DIRECTORY) -
  861. DebugDirectorySize);
  862. }
  863. OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size = DebugDirectorySize;
  864. DbgOffset = DbgFileHeaderSize;
  865. for (i = 0, j=0, DebugDirectory=DbgDebugDirectories;
  866. i < NumberOfDebugDirectories; i++) {
  867. if (DebugDirectory[i].SizeOfData) {
  868. DebugDirectory[j] = DebugDirectory[i];
  869. DebugDirectory[j].AddressOfRawData = 0;
  870. DebugDirectory[j].PointerToRawData = DbgOffset;
  871. DbgOffset += (DebugDirectory[j].SizeOfData + 3 )& ~3;
  872. j++;
  873. }
  874. }
  875. if (FunctionTable) {
  876. FunctionTableDir.PointerToRawData -= sizeof(IMAGE_DEBUG_DIRECTORY) * (NumberOfDebugDirectories - j);
  877. }
  878. NumberOfDebugDirectories = j;
  879. CheckSumMappedFile( ImageBase,
  880. NewFileSize,
  881. &HeaderSum,
  882. &CheckSum
  883. );
  884. OptionalHeader->CheckSum = CheckSum;
  885. DbgFileHeader.Signature = IMAGE_SEPARATE_DEBUG_SIGNATURE;
  886. DbgFileHeader.Flags = 0;
  887. DbgFileHeader.Machine = FileHeader->Machine;
  888. DbgFileHeader.Characteristics = FileHeader->Characteristics;
  889. DbgFileHeader.TimeDateStamp = FileHeader->TimeDateStamp;
  890. DbgFileHeader.CheckSum = CheckSum;
  891. DbgFileHeader.ImageBase = OptionalHeader->ImageBase;
  892. DbgFileHeader.SizeOfImage = OptionalHeader->SizeOfImage;
  893. DbgFileHeader.ExportedNamesSize = ExportedNamesSize;
  894. DbgFileHeader.DebugDirectorySize = NumberOfDebugDirectories * sizeof(IMAGE_DEBUG_DIRECTORY);
  895. if (FunctionTable) {
  896. DbgFileHeader.DebugDirectorySize += sizeof (IMAGE_DEBUG_DIRECTORY);
  897. }
  898. DbgFileHeader.NumberOfSections = FileHeader->NumberOfSections;
  899. memset( DbgFileHeader.Reserved, 0, sizeof( DbgFileHeader.Reserved ) );
  900. DbgFileHeader.SectionAlignment = OptionalHeader->SectionAlignment;
  901. SetFilePointer( SymbolFileHandle, 0, NULL, FILE_BEGIN );
  902. WriteFile( SymbolFileHandle,
  903. &DbgFileHeader,
  904. sizeof( DbgFileHeader ),
  905. &BytesWritten,
  906. NULL
  907. );
  908. if (NtHeaders) {
  909. Sections = IMAGE_FIRST_SECTION( NtHeaders );
  910. } else {
  911. Sections = (PIMAGE_SECTION_HEADER)
  912. ((ULONG_PTR)ImageBase +
  913. ((PIMAGE_FILE_HEADER)ImageBase)->SizeOfOptionalHeader +
  914. IMAGE_SIZEOF_FILE_HEADER );
  915. }
  916. WriteFile( SymbolFileHandle,
  917. (PVOID)Sections,
  918. sizeof( IMAGE_SECTION_HEADER ) * FileHeader->NumberOfSections,
  919. &BytesWritten,
  920. NULL
  921. );
  922. if (ExportedNamesSize) {
  923. WriteFile( SymbolFileHandle,
  924. ExportedNames,
  925. ExportedNamesSize,
  926. &BytesWritten,
  927. NULL
  928. );
  929. }
  930. WriteFile( SymbolFileHandle,
  931. DbgDebugDirectories,
  932. sizeof (IMAGE_DEBUG_DIRECTORY) * NumberOfDebugDirectories,
  933. &BytesWritten,
  934. NULL );
  935. if (FunctionTable) {
  936. WriteFile( SymbolFileHandle,
  937. &FunctionTableDir,
  938. sizeof (IMAGE_DEBUG_DIRECTORY),
  939. &BytesWritten,
  940. NULL );
  941. WriteFile( SymbolFileHandle,
  942. FunctionTable,
  943. FunctionTableSize,
  944. &BytesWritten,
  945. NULL
  946. );
  947. }
  948. SetFilePointer( SymbolFileHandle, 0, NULL, FILE_END );
  949. nomisc:
  950. FlushViewOfFile( ImageBase, NewFileSize );
  951. UnmapViewOfFile( ImageBase );
  952. SetFilePointer( FileHandle, NewFileSize, NULL, FILE_BEGIN );
  953. SetEndOfFile( FileHandle );
  954. TouchFileTimes( FileHandle, NULL );
  955. bSplitSymRetValue=TRUE;
  956. __leave;
  957. } else {
  958. CloseHandle( SymbolFileHandle );
  959. DeleteFile( SymbolFilePath );
  960. }
  961. nosyms:
  962. dwLastError = GetLastError();
  963. #endif
  964. } __except(EXCEPTION_EXECUTE_HANDLER) {
  965. dwLastError = GetExceptionCode();
  966. }
  967. // SymFree checks that the pointer passed isn't null and
  968. // sets the pointer to null after freeing the memory
  969. SymFree(DbgDebugDirectories);
  970. SymFree(ExportedNames);
  971. SymFree(FpoTable);
  972. SymFree(FunctionTable);
  973. SymFree(NewDebugData);
  974. if (FileHandle != INVALID_HANDLE_VALUE) {
  975. CloseHandle(FileHandle);
  976. }
  977. if (SymbolFileHandle != INVALID_HANDLE_VALUE) {
  978. CloseHandle(SymbolFileHandle);
  979. }
  980. if (ImageBase) {
  981. UnmapViewOfFile(ImageBase);
  982. }
  983. if (dwLastError != 0) {
  984. SetLastError(dwLastError);
  985. }
  986. return(bSplitSymRetValue);
  987. }
  988. #if defined(use_SplitSymbolsX)
  989. LPSTR CharNext(
  990. LPCSTR lpCurrentChar)
  991. {
  992. if (IsDBCSLeadByte(*lpCurrentChar)) {
  993. lpCurrentChar++;
  994. }
  995. /*
  996. * if we have only DBCS LeadingByte, we will point string-terminaler.
  997. */
  998. if (*lpCurrentChar) {
  999. lpCurrentChar++;
  1000. }
  1001. return (LPSTR)lpCurrentChar;
  1002. }
  1003. LPSTR CharPrev(
  1004. LPCSTR lpStart,
  1005. LPCSTR lpCurrentChar)
  1006. {
  1007. if (lpCurrentChar > lpStart) {
  1008. LPCSTR lpChar;
  1009. BOOL bDBC = FALSE;
  1010. for (lpChar = --lpCurrentChar - 1 ; lpChar >= lpStart ; lpChar--) {
  1011. if (!IsDBCSLeadByte(*lpChar))
  1012. break;
  1013. bDBC = !bDBC;
  1014. }
  1015. if (bDBC)
  1016. lpCurrentChar--;
  1017. }
  1018. return (LPSTR)lpCurrentChar;
  1019. }
  1020. #endif