Windows NT 4.0 source code leak
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.

1032 lines
23 KiB

4 years ago
  1. /***********************************************************************
  2. * Microsoft (R) 32-Bit Incremental Linker
  3. *
  4. * Copyright (C) Microsoft Corp 1992-95. All rights reserved.
  5. *
  6. * File: image.cpp
  7. *
  8. * File Comments:
  9. *
  10. * This file contains functions that manipulate the image data structure.
  11. *
  12. ***********************************************************************/
  13. #include "link.h"
  14. #include "image_.h" // private definitions
  15. const BYTE DosHeaderArray[] = {
  16. 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  17. 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  18. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19. #ifdef JAPAN
  20. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00,
  21. 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x82, 0xb1,
  22. 0x82, 0xcc, 0x83, 0x76, 0x83, 0x8d, 0x83, 0x4f, 0x83, 0x89, 0x83, 0x80, 0x82, 0xcd, 0x81, 0x41,
  23. 0x4d, 0x53, 0x2d, 0x44, 0x4f, 0x53, 0x20, 0x83, 0x82, 0x81, 0x5b, 0x83, 0x68, 0x82, 0xc5, 0x82,
  24. 0xcd, 0x8e, 0xc0, 0x8d, 0x73, 0x82, 0xc5, 0x82, 0xab, 0x82, 0xdc, 0x82, 0xb9, 0x82, 0xf1, 0x81,
  25. 0x42, 0x20, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  26. #else // !JAPAN
  27. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
  28. 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 'T', 'h',
  29. 'i', 's', ' ', 'p', 'r', 'o', 'g', 'r', 'a', 'm', ' ', 'c', 'a', 'n', 'n', 'o',
  30. 't', ' ', 'b', 'e', ' ', 'r', 'u', 'n', ' ', 'i', 'n', ' ', 'D', 'O', 'S', ' ',
  31. 'm', 'o', 'd', 'e', 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  32. #endif // !JAPAN
  33. 0x50, 0x45, 0x00, 0x00 // PE Signature
  34. };
  35. #define cbDosHeaderArray sizeof(DosHeaderArray)
  36. const LONG DosHeaderSize = cbDosHeaderArray;
  37. static const BYTE MacDosHeaderArray[] = {
  38. 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
  39. 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  40. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  41. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
  42. 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 'T', 'h',
  43. 'i', 's', ' ', 'p', 'r', 'o', 'g', 'r', 'a', 'm', ' ', 'i', 's', ' ', 'a', ' ',
  44. 'M', 'a', 'c', 'i', 'n', 't', 'o', 's', 'h', ' ', 'E', 'X', 'E', 0x2e, 0x0d, 0x0d,
  45. 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  46. 0x50, 0x45, 0x00, 0x00 // PE Signature
  47. };
  48. #define cbMacDosHeaderArray sizeof(MacDosHeaderArray);
  49. void
  50. InitImage (
  51. IN OUT PPIMAGE ppimage,
  52. IN IMAGET imaget
  53. )
  54. /*++
  55. Routine Description:
  56. Initializes an IMAGE structure.
  57. Arguments:
  58. ppimage - pointer to an image struct ptr.
  59. Return Value:
  60. None.
  61. --*/
  62. {
  63. // Alloc space & initialize image struct
  64. *ppimage = (PIMAGE) Calloc(1, sizeof(IMAGE));
  65. (*ppimage)->imaget = imaget;
  66. // initialize headers/switches with default values
  67. (*ppimage)->pvBase = *ppimage;
  68. (*ppimage)->MajVersNum = INCDB_MAJVERSNUM;
  69. (*ppimage)->MinVersNum = INCDB_MINVERSNUM;
  70. strcpy((*ppimage)->Sig, INCDB_SIGNATURE);
  71. (*ppimage)->ImgFileHdr = DefImageFileHdr;
  72. (*ppimage)->ImgOptHdr = DefImageOptionalHdr;
  73. (*ppimage)->Switch = DefSwitch;
  74. (*ppimage)->SwitchInfo = DefSwitchInfo;
  75. // initialize the symbol table
  76. InitExternalSymbolTable(&(*ppimage)->pst, celementInChunkSym, cchunkInDirSym);
  77. InitExternalSymbolTable(&(*ppimage)->pstDirective,
  78. celementInChunkDirective, cchunkInDirDirective);
  79. // initialize libs
  80. InitLibs(&(*ppimage)->libs);
  81. // initialize section list
  82. (*ppimage)->secs.psecHead = NULL;
  83. (*ppimage)->secs.ppsecTail = &(*ppimage)->secs.psecHead;
  84. switch (imaget) {
  85. case imagetPE:
  86. (*ppimage)->pbDosHeader = DosHeaderArray;
  87. (*ppimage)->cbDosHeader = cbDosHeaderArray;
  88. (*ppimage)->CbHdr = CbHdrPE;
  89. (*ppimage)->WriteSectionHeader = WriteSectionHeaderPE;
  90. (*ppimage)->WriteHeader = WriteHeaderPE;
  91. break;
  92. case imagetVXD:
  93. (*ppimage)->pbDosHeader = DosHeaderArray;
  94. (*ppimage)->cbDosHeader = cbDosHeaderArray - 4; // no "PE00" needed
  95. (*ppimage)->CbHdr = CbHdrVXD;
  96. (*ppimage)->WriteSectionHeader = WriteSectionHeaderVXD;
  97. (*ppimage)->WriteHeader = WriteHeaderVXD;
  98. InitImageVXD(*ppimage);
  99. break;
  100. default:
  101. assert(FALSE);
  102. }
  103. }
  104. void
  105. SetMacImage(PIMAGE pimage)
  106. {
  107. pimage->pbDosHeader = MacDosHeaderArray;
  108. pimage->cbDosHeader = cbMacDosHeaderArray;
  109. }
  110. // incremental init of image
  111. void
  112. IncrInitImage (
  113. IN OUT PPIMAGE ppimage
  114. )
  115. {
  116. assert(ppimage);
  117. assert(*ppimage);
  118. assert((*ppimage)->pst);
  119. // init symbol tables
  120. IncrInitExternalSymbolTable(&(*ppimage)->pst);
  121. IncrInitExternalSymbolTable(&(*ppimage)->pstDirective);
  122. imodidx = (*ppimage)->imodidx;
  123. }
  124. // get next addr for Win95
  125. PVOID
  126. NextMapAddrWin95 (
  127. PVOID pvCur
  128. )
  129. {
  130. if (!pvCur) {
  131. return (PVOID) 0x90000000;
  132. }
  133. if (pvCur < (PVOID) 0xC0000000) {
  134. return (PVOID) ((BYTE *) pvCur + ILKMAP_MAX);
  135. } else {
  136. return (PVOID) (-1);
  137. }
  138. }
  139. // return map address for NT
  140. PVOID
  141. NextMapAddrWinNT (
  142. PVOID pvCur
  143. )
  144. {
  145. if (!pvCur) {
  146. return (PVOID) 0x3FFF0000;
  147. }
  148. if (pvCur < (PVOID) 0x7FFFFFFF) {
  149. return (PVOID)((BYTE *) pvCur+ILKMAP_MAX);
  150. } else {
  151. return (PVOID)(-1);
  152. }
  153. }
  154. // returns the next map address to try
  155. PVOID
  156. NextMapAddr (
  157. BOOL fOnWin95,
  158. PVOID pvCur
  159. )
  160. {
  161. return (fOnWin95 ? NextMapAddrWin95(pvCur) : NextMapAddrWinNT(pvCur));
  162. }
  163. BOOL
  164. FVerifyEXE(
  165. const char *szExe,
  166. PIMAGE pimage
  167. )
  168. /*++
  169. Routine Description:
  170. Verifies size & timestamp of EXE.
  171. Arguments:
  172. szExe - name of EXE.
  173. pimage - ptr to IMAGE struct.
  174. Return Value:
  175. TRUE if EXE verified as what was left during previous link.
  176. --*/
  177. {
  178. struct _stat statfile;
  179. if (_stat(szExe, &statfile) == -1) {
  180. #ifdef INSTRUMENT
  181. LogNoteEvent(Log, SZILINK, NULL, letypeEvent, "didn't find exe - %s", szExe);
  182. #endif // INSTRUMENT
  183. return(FALSE);
  184. }
  185. if (pimage->tsExe != (DWORD)statfile.st_mtime ||
  186. pimage->cbExe != (DWORD)statfile.st_size) {
  187. #ifdef INSTRUMENT
  188. LogNoteEvent(Log, SZILINK, NULL, letypeEvent, "exe size or timestamp differ - %s", szExe);
  189. #endif // INSTRUMENT
  190. return(FALSE);
  191. }
  192. return(TRUE);
  193. }
  194. // figure out if we are running on NT
  195. BOOL
  196. IsOSWin95 (
  197. VOID
  198. )
  199. {
  200. DWORD dw = GetVersion();
  201. return ( (HIWORD(dw) & ~(0x7FFF)) &&
  202. (LOBYTE(LOWORD(dw)) >= 0x4) );
  203. }
  204. void
  205. DetachMiscFromHeap (
  206. PIMAGE pimage
  207. )
  208. /*++
  209. Routine Description:
  210. This is the reverse of AppendMiscToHeap(). Anything
  211. that could be realloc'ed for instance needs to be
  212. detached from the heap.
  213. The order in which things get detached should be the
  214. reverse of their attachment.
  215. Currently only the string block is detached
  216. Arguments:
  217. pimage - pointer to an image.
  218. Return Value:
  219. None.
  220. --*/
  221. {
  222. BYTE *pbNew;
  223. // empty string table
  224. if (!pimage->pst->blkStringTable.cb) {
  225. return;
  226. }
  227. // alloc space
  228. pbNew = (BYTE *) PvAlloc(pimage->pst->blkStringTable.cbAlloc);
  229. // copy from heap
  230. memcpy(pbNew, pimage->pst->blkStringTable.pb,
  231. pimage->pst->blkStringTable.cb);
  232. // free up heap space
  233. Free(pimage->pst->blkStringTable.pb, Align(sizeof(DWORD),pimage->pst->blkStringTable.cb));
  234. // update string blk
  235. pimage->pst->blkStringTable.pb = pbNew;
  236. }
  237. // sets up for a full ilink
  238. void
  239. SetupForFullIlinkBuild (
  240. PPIMAGE ppimage
  241. )
  242. {
  243. PIMAGE pimageO = (*ppimage); // save a pointer to image on heap
  244. BOOL fOnWin95 = IsOSWin95(); // figure out if we are on NT
  245. PVOID pvCur = (PVOID)0;
  246. DWORD dwErr = 0;
  247. // create the private heap
  248. while ((pvCur = NextMapAddr(fOnWin95, pvCur)) != (PVOID)-1) {
  249. if (CreateHeap(pvCur, 0, TRUE, &dwErr) == (PVOID)-1) {
  250. switch (dwErr) {
  251. case ERROR_DISK_FULL:
  252. Warning(NULL, LOWSPACE);
  253. fINCR = FALSE;
  254. return;
  255. case ERROR_FILE_NOT_FOUND:
  256. case ERROR_PATH_NOT_FOUND:
  257. Fatal(NULL, CANTOPENFILE, OutFilename);
  258. default: // address busy etc.
  259. // for Win95 only
  260. if (fOnWin95 && !FFreeDiskSpace(cbInitialILKMapSize)) {
  261. Warning(NULL, LOWSPACE);
  262. fINCR = FALSE;
  263. return;
  264. }
  265. continue;
  266. } // end switch
  267. } else {
  268. break;
  269. }
  270. } // end while
  271. // check to see if we succeeded in creating the map
  272. if (pvCur == (PVOID)-1) {
  273. #ifdef INSTRUMENT
  274. LogNoteEvent(Log, SZILINK, NULL, letypeEvent, "failed to create heap");
  275. #endif // INSTRUMENT
  276. PostNote(NULL, UNABLETOCREATEMAP);
  277. fINCR = FALSE;
  278. return;
  279. }
  280. #ifdef INSTRUMENT
  281. LogNoteEvent(Log, SZILINK, NULL, letypeEvent, "created heap at 0x%.8lx", pvCur);
  282. #endif // INSTRUMENT
  283. // create and initialize image on private heap
  284. InitImage(ppimage, pimageO->imaget);
  285. // transfer switches & related info to image on private heap
  286. TransferLinkerSwitchValues((*ppimage), pimageO);
  287. // free the image on ordinary heap
  288. FreeImage(&pimageO, FALSE);
  289. }
  290. // sets up for an incremental ilink
  291. void
  292. SetupForIncrIlinkBuild (
  293. PPIMAGE ppimage,
  294. PVOID pvbase,
  295. DWORD cbLen
  296. )
  297. {
  298. PVOID pv;
  299. PIMAGE pimageN = (*ppimage); // save a pointer to new image on heap
  300. PST pst;
  301. DWORD dwErr;
  302. // try to create private heap at base specified
  303. if ((pv = CreateHeap(pvbase, cbLen, FALSE, &dwErr)) == (PVOID)-1) {
  304. #ifdef INSTRUMENT
  305. LogNoteEvent(Log, SZILINK, NULL, letypeEvent, "failed to create heap at 0x%.8lx", pvbase);
  306. #endif // INSTRUMENT
  307. if (fTest) {
  308. PostNote(NULL, UNABLETOLOADILK);
  309. }
  310. // failed to create heap at base: try to do a full ilink
  311. SetupForFullIlinkBuild(ppimage);
  312. return;
  313. }
  314. // set the base map address
  315. *ppimage = (PIMAGE) pv;
  316. // check the string table ptr and verify nothing beyond it.
  317. pst = (*ppimage)->pst;
  318. if (pst->blkStringTable.cb &&
  319. (!FValidPtrInfo((DWORD)pv, cbLen, (DWORD)pst->blkStringTable.pb, pst->blkStringTable.cb)
  320. || (Align(sizeof(DWORD),((DWORD)pst->blkStringTable.pb+pst->blkStringTable.cb-(DWORD)pv)) != cbLen))) {
  321. #ifdef INSTRUMENT
  322. LogNoteEvent(Log, SZILINK, NULL, letypeEvent, "inavlid ptrs in symbol table");
  323. #endif // INSTRUMENT
  324. if (fTest) {
  325. PostNote(NULL, CORRUPTILK);
  326. }
  327. // cannot do an incr ilink; try to do a full ilink
  328. FreeHeap();
  329. (*ppimage) = pimageN;
  330. SetupForFullIlinkBuild(ppimage);
  331. return;
  332. }
  333. // detach string table etc from heap
  334. DetachMiscFromHeap(*ppimage);
  335. // compare switches to see if we can continue
  336. if (!CheckAndUpdateLinkerSwitches(pimageN, (*ppimage))) {
  337. #ifdef INSTRUMENT
  338. LogNoteEvent(Log, SZILINK, NULL, letypeEvent, "incompatible switches");
  339. #endif // INSTRUMENT
  340. // cannot do an incr ilink; try to do a full ilink
  341. if (fTest) {
  342. PostNote(NULL, LNKOPTIONSCHNG);
  343. }
  344. FreeHeap();
  345. (*ppimage) = pimageN;
  346. SetupForFullIlinkBuild(ppimage);
  347. return;
  348. }
  349. // OK to proceed with incr ilink
  350. FreeImage(&pimageN, FALSE);
  351. fIncrDbFile = TRUE;
  352. }
  353. char *
  354. SzGenIncrDbFilename (
  355. PIMAGE pimage
  356. )
  357. /*++
  358. Routine Description:
  359. Generates the ILK filename.
  360. Either uses -out: specified by user or first name of
  361. obj file & then uses default name. Incr db name may
  362. not match output filename if it is specified via
  363. a directive in one of the objs.
  364. Arguments:
  365. pimage - pointer to an image.
  366. Return Value:
  367. Pointer to (malloc'ed) name of incr db filename
  368. --*/
  369. {
  370. char szDrive[_MAX_DRIVE];
  371. char szDir[_MAX_DIR];
  372. char szFname[_MAX_FNAME];
  373. char szIncrDbPath[_MAX_PATH];
  374. // Generate incr db filename
  375. if (OutFilename == NULL) {
  376. DWORD i;
  377. PARGUMENT_LIST arg;
  378. // Capture first object name for output filename.
  379. for (i = 0, arg = FilenameArguments.First;
  380. i < FilenameArguments.Count;
  381. i++, arg = arg->Next) {
  382. INT Handle;
  383. BOOL fArchive;
  384. Handle = FileOpen(arg->OriginalName, O_RDONLY | O_BINARY, 0);
  385. fArchive = IsArchiveFile(arg->OriginalName, Handle);
  386. FileClose(Handle, FALSE);
  387. if (fArchive) {
  388. continue;
  389. }
  390. SetDefaultOutFilename(pimage, arg);
  391. break;
  392. }
  393. }
  394. if (OutFilename == NULL) {
  395. return NULL;
  396. }
  397. assert(OutFilename);
  398. _splitpath(OutFilename, szDrive, szDir, szFname, NULL);
  399. _makepath(szIncrDbPath, szDrive, szDir, szFname, INCDB_EXT);
  400. return(SzDup(szIncrDbPath));
  401. }
  402. void
  403. SaveStringTable (
  404. IN PST pst
  405. )
  406. /*++
  407. Routine Description:
  408. Saves the string table.
  409. Arguments:
  410. pst - pointer to symbol table whose string table is to be saved.
  411. Return Value:
  412. None.
  413. --*/
  414. {
  415. BYTE *pb;
  416. // empty string table
  417. if (!pst->blkStringTable.cb) {
  418. return;
  419. }
  420. // append long name string table
  421. pb = (BYTE *) Malloc(pst->blkStringTable.cb);
  422. memcpy(pb, pst->blkStringTable.pb,
  423. pst->blkStringTable.cb);
  424. pst->blkStringTable.pb = pb;
  425. }
  426. void
  427. AppendMiscToHeap (
  428. PIMAGE pimage
  429. )
  430. /*++
  431. Routine Description:
  432. Appends anything that could not be allocated on the heap
  433. to during the link process. Currently only the long name
  434. table is appended.
  435. Arguments:
  436. pimage - pointer to an image.
  437. Return Value:
  438. None.
  439. --*/
  440. {
  441. // save the string table holding all the directives (full-link only)
  442. if (!fIncrDbFile) {
  443. SaveStringTable(pimage->pstDirective);
  444. }
  445. // save the string table of the symbols
  446. SaveStringTable(pimage->pst);
  447. }
  448. void
  449. WriteIncrDbFile (
  450. PIMAGE pimage
  451. )
  452. /*++
  453. Routine Description:
  454. Writes out an image to database. Assumes that file is open
  455. if it already existed. Currently simply writes out entire
  456. image.
  457. Arguments:
  458. pimage - pointer to an image.
  459. fExists - TRUE if incr db file already exists.
  460. Return Value:
  461. None.
  462. --*/
  463. {
  464. assert(FileIncrDbHandle);
  465. // copy over long name table (etc.) to heap
  466. AppendMiscToHeap(pimage);
  467. // do cleanup
  468. CloseHeap();
  469. // write out & close file
  470. FileClose(FileIncrDbHandle, TRUE);
  471. }
  472. void
  473. ReadIncrDbFile (
  474. PPIMAGE ppimage
  475. )
  476. /*++
  477. Routine Description:
  478. Reads in an image database. Reads in header alone,
  479. verifies, read in rest of db.
  480. Arguments:
  481. ppimage - pointer to an image struct pointer
  482. Handle - handle of image file
  483. Return Value:
  484. None.
  485. --*/
  486. {
  487. struct _stat statfile;
  488. IMAGE image;
  489. HANDLE hFile;
  490. // establish name of the db file
  491. szIncrDbFilename = SzGenIncrDbFilename(*ppimage);
  492. if (!szIncrDbFilename) {
  493. fINCR = FALSE;
  494. return;
  495. }
  496. // verify that ILK file exists and is valid
  497. if (!FValidILKFile(szIncrDbFilename, TRUE, &image, &statfile)) {
  498. // full build possible if ILK is corrupt or has an old format etc.
  499. if (fINCR) {
  500. SetupForFullIlinkBuild(ppimage);
  501. }
  502. return;
  503. }
  504. // ensure that the previously built EXE is valid and still around.
  505. assert(OutFilename);
  506. if (!FVerifyEXE(OutFilename, &image)) {
  507. PostNote(NULL, FILECHANGED, OutFilename);
  508. (*ppimage)->Switch.Link.fNotifyFullBuild = FALSE;
  509. SetupForFullIlinkBuild(ppimage);
  510. return;
  511. }
  512. // check to see if file isn't locked by another process
  513. hFile = CreateFile(OutFilename,
  514. GENERIC_READ | GENERIC_WRITE,
  515. 0, NULL,
  516. OPEN_EXISTING,
  517. FILE_ATTRIBUTE_NORMAL,
  518. NULL);
  519. if (hFile == INVALID_HANDLE_VALUE) {
  520. FatalNoDelete(NULL, INVALID_FILEPERM, OutFilename);
  521. exit(INVALID_FILEPERM);
  522. } else {
  523. CloseHandle(hFile);
  524. }
  525. if (image.Switch.Link.DebugInfo != None) {
  526. // Ensure that the PDB file exists and has the right permissions
  527. char *szPdb;
  528. szPdb = DeterminePDBFilename(OutFilename, PdbFilename);
  529. if (_access(szPdb, 0) == -1) {
  530. PostNote(NULL, PDBMISSING, szPdb);
  531. FreePv(szPdb);
  532. SetupForFullIlinkBuild(ppimage);
  533. return;
  534. }
  535. if (_access(szPdb, 2) == -1) {
  536. FatalNoDelete(NULL, INVALID_FILEPERM, szPdb);
  537. exit(INVALID_FILEPERM);
  538. }
  539. PdbFilename = szPdb;
  540. }
  541. // set up for an incr ilink.
  542. SetupForIncrIlinkBuild(ppimage, image.pvBase, (DWORD)statfile.st_size);
  543. if (!fIncrDbFile) {
  544. return;
  545. }
  546. // incremental initialization
  547. IncrInitImage(ppimage);
  548. DBEXEC(DB_DUMPIMAGE, DumpImage(*ppimage));
  549. }
  550. BOOL
  551. FValidPtrInfo (
  552. IN DWORD pvBase,
  553. IN DWORD fileLen,
  554. IN DWORD ptr,
  555. IN DWORD cbOffset
  556. )
  557. /*++
  558. Routine Description:
  559. Ensures that the ptr and offset are valid.
  560. Arguments:
  561. pvBase - base of image.
  562. fileLen - length of file.
  563. ptr - ptr to validate.
  564. cbOffset - cbOffset from ptr that has to be valid as well.
  565. Return Value:
  566. TRUE if info is valid.
  567. --*/
  568. {
  569. if (ptr <= (DWORD)pvBase) {
  570. // Invalid ptr?
  571. return(FALSE);
  572. }
  573. ptr -= (DWORD) pvBase; // take out the base value
  574. if ((ptr + cbOffset) <= fileLen) {
  575. return(TRUE);
  576. }
  577. return(FALSE);
  578. }
  579. void
  580. FreeImage (
  581. PPIMAGE ppimage,
  582. BOOL fIncrBuild
  583. )
  584. /*++
  585. Routine Description:
  586. Free space occupied by image blowing away structures as needed
  587. Arguments:
  588. pimage - pointer to image struct pointer
  589. Return Value:
  590. None.
  591. --*/
  592. {
  593. // free stuff according to whether it is an incr build
  594. if (fIncrBuild) {
  595. FreeHeap();
  596. } else {
  597. // FreeImageMap(ppimage);
  598. FreeExternalSymbolTable(&((*ppimage)->pst));
  599. // UNDONE: This memory is allocated via Calloc() and isn't safe to free
  600. free(*ppimage);
  601. }
  602. // done
  603. *ppimage = NULL;
  604. }
  605. void
  606. SaveEXEInfo(
  607. const char *szExe,
  608. PIMAGE pimage
  609. )
  610. /*++
  611. Routine Description:
  612. Saves size & timestamp of EXE.
  613. Arguments:
  614. szExe - name of EXE.
  615. pimage - ptr to IMAGE struct.
  616. Return Value:
  617. None.
  618. --*/
  619. {
  620. struct _stat statfile;
  621. if (_stat(szExe, &statfile) == -1) {
  622. Fatal(NULL, CANTOPENFILE, szExe);
  623. }
  624. pimage->tsExe = statfile.st_mtime;
  625. pimage->cbExe = statfile.st_size;
  626. }
  627. BOOL
  628. FValidILKFile (
  629. const char *szIncrDbFilename,
  630. BOOL fIlink,
  631. PIMAGE pimage,
  632. struct _stat *pstat
  633. )
  634. /*++
  635. Routine Description:
  636. Verifies that file is a valid ILK file.
  637. Arguments:
  638. szIncrDbFilename - name of ILK file.
  639. fIlink - is TRUE if we are attempting to do an ilink.
  640. pimage - ptr to IMAGE struct.
  641. pstat - ptr to a statfile struct.
  642. Return Value:
  643. TRUE if file is a valid ILK file.
  644. --*/
  645. {
  646. // stat the incremental db file to make sure it is around.
  647. if (_stat(szIncrDbFilename, pstat)) {
  648. return(FALSE);
  649. }
  650. // the ILK file is around and so we are not doing a full link
  651. // if we do, the resulting warning will let the user know about anyway.
  652. pimage->Switch.Link.fNotifyFullBuild = FALSE;
  653. // make sure the file is of proper size
  654. if (pstat->st_size < sizeof(IMAGE) || pstat->st_size > ILKMAP_MAX) {
  655. if (fIlink) {
  656. #ifdef INSTRUMENT
  657. LogNoteEvent(Log, SZILINK, NULL, letypeEvent, "invalid size for a ILK file");
  658. #endif // INSTRUMENT
  659. Warning(NULL, INVALID_DBFILE, szIncrDbFilename);
  660. fINCR = FALSE;
  661. }
  662. return(FALSE);
  663. }
  664. // make sure file has proper permissions.
  665. if ((pstat->st_mode & (S_IREAD | S_IWRITE)) != (S_IREAD | S_IWRITE)) {
  666. if (fIlink) {
  667. Warning(NULL, INVALID_FILE_ATTRIB, szIncrDbFilename);
  668. fINCR = FALSE;
  669. }
  670. return(FALSE);
  671. }
  672. // open the incremental db file
  673. FileIncrDbHandle = FileOpen(szIncrDbFilename, O_RDWR | O_BINARY, 0);
  674. // read in just the image structure
  675. if (FileRead(FileIncrDbHandle, pimage, sizeof(IMAGE)) != sizeof(IMAGE)) {
  676. FileClose(FileIncrDbHandle, TRUE);
  677. if (fIlink) {
  678. Warning(NULL, INVALID_DBFILE, szIncrDbFilename);
  679. fINCR = FALSE;
  680. }
  681. return(FALSE);
  682. }
  683. // close the incremental db file
  684. FileClose(FileIncrDbHandle, TRUE);
  685. FileIncrDbHandle = 0;
  686. // look for the incr db signature
  687. if (strcmp(pimage->Sig, INCDB_SIGNATURE)) {
  688. if (fIlink) {
  689. #ifdef INSTRUMENT
  690. LogNoteEvent(Log, SZILINK, NULL, letypeEvent, "invalid sig found");
  691. #endif // INSTRUMENT
  692. Warning(NULL, INVALID_DBFILE, szIncrDbFilename);
  693. fINCR = FALSE;
  694. }
  695. return(FALSE);
  696. }
  697. // if not doing an ilink, just verifying the signature will do for now
  698. if (!fIlink) {
  699. return(TRUE);
  700. }
  701. // verify the version numbers; mimatch => do a full inc build
  702. if (pimage->MajVersNum != INCDB_MAJVERSNUM) {
  703. #ifdef INSTRUMENT
  704. LogNoteEvent(Log, SZILINK, NULL, letypeEvent, "invalid version found");
  705. #endif // INSTRUMENT
  706. if (fTest) {
  707. PostNote(NULL, INVALIDILKFORMAT);
  708. }
  709. return(FALSE);
  710. }
  711. // verify ptrs in image struct
  712. if (!FValidPtrInfo((DWORD)pimage->pvBase, (DWORD)pstat->st_size, (DWORD)pimage->secs.psecHead, sizeof(SEC)) ||
  713. !FValidPtrInfo((DWORD)pimage->pvBase, (DWORD)pstat->st_size, (DWORD)pimage->libs.plibHead, sizeof(LIB)) ||
  714. !FValidPtrInfo((DWORD)pimage->pvBase, (DWORD)pstat->st_size, (DWORD)pimage->plibCmdLineObjs, sizeof(LIB)) ||
  715. !FValidPtrInfo((DWORD)pimage->pvBase, (DWORD)pstat->st_size, (DWORD)pimage->pst, sizeof(ST))) {
  716. #ifdef INSTRUMENT
  717. LogNoteEvent(Log, SZILINK, NULL, letypeEvent, "invalid ptrs found in image struct");
  718. #endif // INSTRUMENT
  719. if (fTest) {
  720. PostNote(NULL, CORRUPTILK);
  721. }
  722. return(FALSE);
  723. }
  724. return(TRUE);
  725. }
  726. #if DBG
  727. void
  728. DumpImage (
  729. PIMAGE pimage
  730. )
  731. /*++
  732. Routine Description:
  733. Dumps an image. Others dump routines may be added
  734. as required.
  735. Arguments:
  736. pimage - pointer to an image.
  737. Return Value:
  738. None.
  739. --*/
  740. {
  741. assert(pimage);
  742. assert(pimage->secs.psecHead);
  743. assert(pimage->libs.plibHead);
  744. assert(pimage->pst);
  745. assert(pimage->pst->pht);
  746. DBPRINT("---------------- IMAGE DUMP ----------------\n");
  747. DBPRINT("Image Base...........0x%.8lx\n\n",(LONG)(pimage->pvBase));
  748. DumpImageMap(&pimage->secs);
  749. DumpDriverMap(pimage->libs.plibHead);
  750. Statistics_HT(pimage->pst->pht);
  751. Dump_HT(pimage->pst->pht, &pimage->pst->blkStringTable);
  752. DBPRINT("------------ END IMAGE DUMP ----------------\n");
  753. }
  754. #endif // DBG