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.

2283 lines
39 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: contrib.cpp
  7. *
  8. * File Comments:
  9. *
  10. * Manipulators for contributors.
  11. *
  12. ***********************************************************************/
  13. #include "link.h"
  14. WORD csec;
  15. extern VOID ProcessSectionFlags(DWORD *, const char *, PIMAGE_OPTIONAL_HEADER);
  16. void
  17. ContribInit(
  18. PPMOD ppmodLinkerDefined)
  19. /*++
  20. Routine Description:
  21. Initialize the contributor manager.
  22. Arguments:
  23. *ppmodLinkerDefined - linker defined module
  24. Return Value:
  25. None.
  26. --*/
  27. {
  28. PMOD pmod;
  29. pmod = (PMOD) Calloc(1, sizeof(MOD));
  30. pmod->plibBack = (PLIB) Calloc(1, sizeof(LIB));
  31. pmod->szFileOrig = Strdup(SZ_LNK_DEF_MOD);
  32. pmod->plibBack->szName = Strdup(SZ_LNK_DEF_LIB);
  33. *ppmodLinkerDefined = pmod;
  34. }
  35. char *
  36. SzComNamePMOD(
  37. PMOD pmod,
  38. char *szBuf)
  39. /*++
  40. Routine Description:
  41. Combines a module name and a library name into a buffer.
  42. Arguments:
  43. pmod - module node in driver map
  44. Return Value:
  45. Combined name.
  46. --*/
  47. {
  48. assert(pmod);
  49. assert(szBuf);
  50. szBuf[0] = '\0';
  51. if (pmod) {
  52. char szFname[_MAX_FNAME];
  53. char szExt[_MAX_EXT];
  54. if (FIsLibPMOD(pmod)) {
  55. _splitpath(SzFilePMOD(pmod), NULL, NULL, szFname, szExt);
  56. strcat(szBuf, szFname);
  57. strcat(szBuf, szExt);
  58. strcat(szBuf, "(");
  59. }
  60. _splitpath(SzOrigFilePMOD(pmod), NULL, NULL, szFname, szExt);
  61. strcat(szBuf, szFname);
  62. strcat(szBuf, szExt);
  63. if (FIsLibPMOD(pmod)) {
  64. strcat(szBuf, ")");
  65. }
  66. }
  67. return(szBuf);
  68. }
  69. char *SzComNamePCON(PCON pcon, char *szBuf)
  70. {
  71. PMOD pmod = PmodPCON(pcon);
  72. if (pmod == pmodLinkerDefined) {
  73. return(NULL);
  74. }
  75. return(SzComNamePMOD(pmod, szBuf));
  76. }
  77. void
  78. ParseSecName(
  79. const char *szName,
  80. const char **pszSec)
  81. /*++
  82. Routine Description:
  83. Parse a COFF section name into a section name.
  84. Arguments:
  85. szName - COFF section name
  86. *pszSec - section name
  87. Return Value:
  88. None.
  89. --*/
  90. {
  91. char *pb;
  92. static char szSec[33];
  93. strncpy(szSec, szName, 32);
  94. *pszSec = szSec;
  95. // Check for group section
  96. pb = strchr(szSec, '$');
  97. if (pb != NULL) {
  98. *pb = '\0';
  99. }
  100. }
  101. PSEC
  102. PsecApplyMergePsec(PSEC psec)
  103. {
  104. PSEC psecOut;
  105. if (psec == NULL) {
  106. return(psec);
  107. }
  108. psecOut = psec;
  109. while (psecOut->psecMerge != NULL) {
  110. psecOut = psecOut->psecMerge;
  111. if (psecOut == psec) {
  112. Fatal(NULL, CIRCULAR_MERGE, psec->szName);
  113. }
  114. }
  115. return(psecOut);
  116. }
  117. PGRP
  118. PgrpFind(
  119. PSEC psec,
  120. const char *szName)
  121. /*++
  122. Routine Description:
  123. Find a group.
  124. Arguments:
  125. psec - section to look in
  126. szName - section name
  127. Return Value:
  128. group if found, NULL otherwise
  129. --*/
  130. {
  131. ENM_GRP enm_grp;
  132. PGRP pgrp = NULL;
  133. psec = PsecApplyMergePsec(psec);
  134. InitEnmGrp(&enm_grp, psec);
  135. while (FNextEnmGrp(&enm_grp)) {
  136. if (strcmp(enm_grp.pgrp->szName, szName) == 0) {
  137. pgrp = enm_grp.pgrp;
  138. break;
  139. }
  140. }
  141. EndEnmGrp(&enm_grp);
  142. return(pgrp);
  143. }
  144. PGRP
  145. PgrpNew(
  146. const char *szName,
  147. PSEC psec)
  148. /*++
  149. Routine Description:
  150. If the group doesn't exist create it, otherwise return existing one.
  151. Arguments:
  152. szName - group name
  153. psec - parent section
  154. Return Value:
  155. pointer to library
  156. --*/
  157. {
  158. PGRP pgrp;
  159. PGRP pgrpCur;
  160. PPGRP ppgrpLast;
  161. assert(psec);
  162. pgrp = PgrpFind(psec, szName);
  163. if (pgrp != NULL) {
  164. return(pgrp);
  165. }
  166. // group not found
  167. // allocate a new group
  168. pgrp = (PGRP) Calloc(1, sizeof(GRP));
  169. pgrp->szName = Strdup(szName);
  170. pgrp->psecBack = psec;
  171. pgrp->cbAlign = 1; // default
  172. // Link group into section in lexical order by name
  173. pgrpCur = psec->pgrpNext;
  174. ppgrpLast = &(psec->pgrpNext);
  175. while (pgrpCur && strcmp(pgrp->szName, pgrpCur->szName) >= 0) {
  176. ppgrpLast = &(pgrpCur->pgrpNext);
  177. pgrpCur = pgrpCur->pgrpNext;
  178. }
  179. *ppgrpLast = pgrp;
  180. pgrp->pgrpNext = pgrpCur;
  181. DBEXEC(DB_CONLOG, DBPRINT("new pgrp = %s\n", pgrp->szName));
  182. return(pgrp);
  183. }
  184. void
  185. ReallyMergePsec(
  186. PSEC psecOld,
  187. PSEC psecNew
  188. )
  189. {
  190. // Move all the cons from this section into the new section. Pick
  191. // the first group since it really doesn't matter.
  192. PGRP pgrpFrom, pgrpTo;
  193. PCON pconFrom, pconTmp;
  194. // Transfer all cons from all groups in psecOld to psecNew
  195. if (psecOld->pgrpNext == NULL) {
  196. return;
  197. }
  198. if (psecNew->pgrpNext == NULL) {
  199. psecNew->pgrpNext = PgrpNew(psecNew->szName, psecNew);
  200. }
  201. pgrpFrom = psecOld->pgrpNext;
  202. pgrpTo = psecNew->pgrpNext;
  203. while (pgrpFrom != NULL) {
  204. pconFrom = pgrpFrom->pconNext;
  205. while (pgrpFrom->ccon != 0) {
  206. pconTmp = pconFrom->pconNext;
  207. pconFrom->pgrpBack = pgrpTo;
  208. pconFrom->pconNext = pgrpTo->pconNext;
  209. pgrpTo->pconNext = pconFrom;
  210. pconFrom = pconTmp;
  211. pgrpFrom->ccon--;
  212. pgrpTo->ccon++;
  213. }
  214. pgrpFrom = pgrpFrom->pgrpNext;
  215. psecOld->pgrpNext = pgrpFrom;
  216. }
  217. }
  218. void
  219. MovePgrp(
  220. const char *szName,
  221. PSEC psecOld,
  222. PSEC psecNew
  223. )
  224. {
  225. PGRP pgrp;
  226. PGRP pgrpCur;
  227. PPGRP ppgrpLast;
  228. assert(psecOld);
  229. assert(psecNew);
  230. if (!(pgrp = PgrpFind(psecOld, szName))) {
  231. // If the group doesn't exist in the old section, nothing to do.
  232. return;
  233. }
  234. // Remove this node from the old section
  235. pgrpCur = psecOld->pgrpNext;
  236. ppgrpLast = &(psecOld->pgrpNext);
  237. while ((pgrpCur != pgrp) && pgrpCur) {
  238. ppgrpLast = &(pgrpCur->pgrpNext);
  239. pgrpCur = pgrpCur->pgrpNext;
  240. }
  241. assert(pgrpCur);
  242. *ppgrpLast = pgrp->pgrpNext;
  243. // Add it to the new section (while maintaining lexical order).
  244. psecNew = PsecApplyMergePsec(psecNew);
  245. pgrpCur = psecNew->pgrpNext;
  246. ppgrpLast = &(psecNew->pgrpNext);
  247. while (pgrpCur && strcmp(pgrp->szName, pgrpCur->szName) >= 0) {
  248. ppgrpLast = &(pgrpCur->pgrpNext);
  249. pgrpCur = pgrpCur->pgrpNext;
  250. }
  251. *ppgrpLast = pgrp;
  252. pgrp->pgrpNext = pgrpCur;
  253. // And update the psec to the new section.
  254. pgrp->psecBack = psecNew;
  255. DBEXEC(DB_CONLOG, DBPRINT("pgrp: %s moved from psec: %s to psec: %s\n",
  256. pgrp->szName,
  257. psecOld->szName,
  258. psecNew->szName));
  259. }
  260. PCON
  261. PconNew(
  262. const char *szName,
  263. DWORD cbRawData,
  264. DWORD flagsPCON,
  265. DWORD flagsPSEC,
  266. PMOD pmod,
  267. PSECS psecs,
  268. PIMAGE pimage)
  269. /*++
  270. Routine Description:
  271. Create a new contributor.
  272. Arguments:
  273. szName - COFF section name
  274. cbRawData - size of raw data
  275. flagsPCON - characteristics from the section in the object
  276. flagsPSEC - characteristics for image destination section
  277. pmod - module contribution came from
  278. Return Value:
  279. pointer to new contribution
  280. --*/
  281. {
  282. PCON pcon;
  283. PGRP pgrp;
  284. PSEC psec;
  285. const char *szSec;
  286. ParseSecName(szName, &szSec);
  287. psec = NULL;
  288. if (pimage->imaget == imagetVXD) {
  289. // For a VxD we relax the flags restrictions and merge everything with the same section
  290. // name into one SEC, since the .def file will probably set the flags anyway.
  291. psec = PsecFindNoFlags(szSec, psecs);
  292. }
  293. if (psec == NULL) {
  294. // Find or create a section with the desired flags.
  295. psec = PsecNew(pmod, szSec, flagsPSEC, psecs, &pimage->ImgOptHdr);
  296. }
  297. pgrp = PgrpNew(szName, psec);
  298. assert(pgrp);
  299. assert(pmod);
  300. if (pmod->icon < pmod->ccon) {
  301. // The initial allocation of CONs hasn't been used up.
  302. // Grab the next available CON from the initial set.
  303. pcon = RgconPMOD(pmod) + pmod->icon;
  304. } else {
  305. size_t cb;
  306. if (fIncrDbFile) {
  307. assert(pmod == pmodLinkerDefined);
  308. }
  309. cb = sizeof(CON);
  310. if (pimage->Switch.Link.fTCE) {
  311. cb += sizeof(NOD);
  312. }
  313. pcon = (PCON) Calloc(1, cb);
  314. }
  315. pmod->icon++;
  316. pgrp->ccon++;
  317. DBEXEC(DB_CONLOG, DBPRINT("new pcon (%p) in group %s\n", pcon, szName));
  318. pcon->cbRawData = cbRawData;
  319. pcon->pgrpBack = pgrp;
  320. pcon->flags = flagsPCON;
  321. pcon->pmodBack = pmod;
  322. if (fIncrDbFile) {
  323. return(pcon);
  324. }
  325. // Add to group
  326. if (pgrp->pconLast) {
  327. assert(pgrp->pconLast->pconNext == NULL);
  328. pgrp->pconLast->pconNext = pcon;
  329. } else {
  330. assert(pgrp->pconNext == NULL);
  331. pgrp->pconNext = pcon;
  332. }
  333. pgrp->pconLast = pcon;
  334. return(pcon);
  335. }
  336. void
  337. DupConInfo (
  338. PCON pconSrc,
  339. PCON pconDst)
  340. /*++
  341. Routine Description:
  342. Duplicates info of a CON. !!!Used by m68k ONLY!!!
  343. Arguments:
  344. pconSrc -
  345. pconDst -
  346. Return Value:
  347. None.
  348. --*/
  349. {
  350. PMOD pmodSrc = PmodPCON(pconSrc);
  351. PMOD pmodDst = PmodPCON(pconDst);
  352. assert(pmodSrc->rgci);
  353. assert(pmodSrc->ccon > (DWORD) IsecPCON(pconSrc));
  354. assert(pmodDst->rgci);
  355. assert(pmodDst->ccon > (DWORD) IsecPCON(pconDst));
  356. pmodDst->rgci[IsecPCON(pconDst)].cReloc = CRelocSrcPCON(pconSrc);
  357. pmodDst->rgci[IsecPCON(pconDst)].cLinenum = CLinenumSrcPCON(pconSrc);
  358. pmodDst->rgci[IsecPCON(pconDst)].foRelocSrc = FoRelocSrcPCON(pconSrc);
  359. pmodDst->rgci[IsecPCON(pconDst)].foLinenumSrc = FoLinenumSrcPCON(pconSrc);
  360. pmodDst->rgci[IsecPCON(pconDst)].foRawDataSrc = FoRawDataSrcPCON(pconSrc);
  361. pmodDst->rgci[IsecPCON(pconDst)].rvaSrc = RvaSrcPCON(pconSrc);
  362. }
  363. PMOD
  364. PmodNew(
  365. const char *szNameMod,
  366. const char *szFileOrig,
  367. DWORD foMember,
  368. DWORD foSymbolTable,
  369. DWORD csymbols,
  370. WORD cbOptHdr,
  371. WORD flags,
  372. WORD ccon,
  373. PLIB plibBack,
  374. BOOL *pfNew)
  375. /*++
  376. Routine Description:
  377. If the module has not been created, create one.
  378. Arguments:
  379. szNameMod - module name, NULL if an archive member
  380. szFileOrig - original module name
  381. foMember - offset of module in archive, only valid if !szName
  382. foSymbolTable - offset to COFF symbol table
  383. csymbols - number of symbols
  384. cbObtHdr - size of optional header
  385. flags - module flags (see ntimage.h for values)
  386. ccon - number of contributions for module
  387. plibBack - pointer to library, dummy library of module is an object file
  388. Return Value:
  389. pointer to new module
  390. --*/
  391. {
  392. PMOD pmod;
  393. assert(szFileOrig);
  394. assert(plibBack);
  395. pmod = PmodFind(plibBack, szFileOrig, foMember);
  396. if (pfNew) {
  397. *pfNew = (pmod == NULL);
  398. }
  399. // if we didn't find it
  400. if (!pmod) {
  401. pmod = (PMOD) Calloc(1, sizeof(MOD) + (ccon * sizeof(CON)));
  402. pmod->rgci = (CONINFO *)PvAllocZ(ccon * sizeof(CONINFO));
  403. if (szNameMod) {
  404. pmod->szNameMod = Strdup(szNameMod);
  405. } else {
  406. pmod->foMember = foMember;
  407. }
  408. if (szFileOrig) {
  409. pmod->szFileOrig = Strdup(szFileOrig);
  410. }
  411. pmod->imod = (fINCR && !fIncrDbFile) ? NewIModIdx() : 0;
  412. if (pmod->imod >= IMODIDXMAC && (fINCR || fPdb)) {
  413. Fatal(NULL, PDBLIMIT, NULL);
  414. }
  415. pmod->foSymbolTable = foSymbolTable;
  416. pmod->csymbols = csymbols;
  417. pmod->cbOptHdr = cbOptHdr;
  418. pmod->flags = flags;
  419. pmod->ccon = ccon;
  420. pmod->plibBack = plibBack;
  421. pmod->pmodNext = plibBack->pmodNext;
  422. if (fINCR) {
  423. pmod->plpextRef = (PLPEXT)Calloc(1, sizeof (LPEXT));
  424. pmod->plpextRef->cpextMax = CPEXT_REFS;
  425. }
  426. if (fPowerMac || fPowerPC) {
  427. DWORD cdwBitVector;
  428. // Allocate bit vectors according to the number of symbols.
  429. cdwBitVector = (csymbols / 32) + 1;
  430. pmod->tocBitVector = fINCR ? Calloc (cdwBitVector, sizeof(DWORD)) :
  431. PvAllocZ(cdwBitVector * sizeof(DWORD));
  432. pmod->writeBitVector = fINCR ? Calloc (cdwBitVector, sizeof(DWORD)) :
  433. PvAllocZ(cdwBitVector * sizeof(DWORD));
  434. pmod->rgpext = fINCR ? (PEXTERNAL *) Calloc (csymbols, sizeof(PEXTERNAL)) :
  435. (PEXTERNAL *) PvAllocZ(csymbols * sizeof(PEXTERNAL));
  436. }
  437. plibBack->pmodNext = pmod;
  438. DBEXEC(DB_CONLOG, {
  439. char szBuf[256];
  440. DBPRINT("new pmod = %s\n", SzComNamePMOD(pmod, szBuf)); });
  441. }
  442. return(pmod);
  443. }
  444. PLIB
  445. PlibNew(
  446. const char *szName,
  447. DWORD foIntMemSymTab,
  448. LIBS *plibs)
  449. /*++
  450. Routine Description:
  451. If the library doesn't exist create it, otherwise return existing one.
  452. Arguments:
  453. szName - library name
  454. foIntMemSymTab - file offset to library interface member symbol table
  455. Return Value:
  456. pointer to library
  457. --*/
  458. {
  459. PLIB plib;
  460. plib = PlibFind(szName, plibs->plibHead, FALSE);
  461. // if we didn't find it
  462. if (!plib) {
  463. // allocate a new library
  464. plib = (PLIB) Calloc(1, sizeof(LIB));
  465. // fill in library node
  466. if (!szName) {
  467. plib->szName = NULL;
  468. } else {
  469. plib->szName = Strdup(szName);
  470. }
  471. plib->foIntMemSymTab = foIntMemSymTab;
  472. plib->pmodNext = NULL;
  473. plib->plibNext = NULL;
  474. *plibs->pplibTail = plib;
  475. plibs->pplibTail = &plib->plibNext;
  476. DBEXEC(DB_CONLOG, DBPRINT("new plib = %s\n", plib->szName));
  477. }
  478. return(plib);
  479. }
  480. void
  481. FreePLIB(
  482. LIBS *plibs)
  483. /*++
  484. Routine Description:
  485. Free a library nodes in the driver map.
  486. Arguments:
  487. None.
  488. Return Value:
  489. None.
  490. --*/
  491. {
  492. ENM_LIB enm_lib;
  493. PLIB plibLast = NULL;
  494. PLIB plib;
  495. InitEnmLib(&enm_lib, plibs->plibHead);
  496. while (FNextEnmLib(&enm_lib)) {
  497. plib = enm_lib.plib;
  498. // UNDONE: It's not safe to call free() for plib because this are
  499. // UNDONE: allocated with Calloc() and not calloc().
  500. free(plibLast);
  501. FreePv(plib->rgulSymMemOff);
  502. FreePv(plib->rgusOffIndex);
  503. FreePv(plib->rgbST);
  504. FreePv(plib->rgszSym);
  505. FreePv(plib->rgbLongFileNames);
  506. plibLast = plib;
  507. }
  508. // UNDONE: It's not safe to call free() for plib because this are
  509. // UNDONE: allocated with Calloc() and not calloc().
  510. free(plibLast);
  511. InitLibs(plibs);
  512. }
  513. PSEC
  514. PsecNew(
  515. PMOD pmod,
  516. const char *szName,
  517. DWORD flags,
  518. PSECS psecs,
  519. PIMAGE_OPTIONAL_HEADER pImgOptHdr)
  520. /*++
  521. Routine Description:
  522. If the section doesn't exist create it, otherwise return existing one.
  523. Arguments:
  524. szName - section name
  525. flags - section flags
  526. Return Value:
  527. pointer to section
  528. --*/
  529. {
  530. PSEC psec;
  531. assert(szName);
  532. // Check if section exists
  533. psec = PsecFind(pmod, szName, flags, psecs, pImgOptHdr);
  534. if (psec != NULL) {
  535. return(psec);
  536. }
  537. ProcessSectionFlags(&flags, szName, pImgOptHdr);
  538. // allocate a new library
  539. psec = (PSEC) Calloc(1, sizeof(SEC));
  540. // fill in section node
  541. psec->szName = Strdup(szName);
  542. psec->flags = flags;
  543. psec->flagsOrig = flags;
  544. psec->pgrpNext = NULL;
  545. psec->psecMerge = NULL;
  546. if (fM68K && (flags & IMAGE_SCN_CNT_CODE)) {
  547. AssignTMAC(psec);
  548. // Init the ResType of this section to whatever the user specified.
  549. // If the user didn't specify anything, default is CODE.
  550. psec->ResTypeMac = sbeCODE;
  551. ApplyM68KSectionResInfo(psec, FALSE);
  552. if (psec->ResTypeMac == sbeCODE) {
  553. fSACodeOnly = FALSE;
  554. }
  555. }
  556. // link library into global list
  557. *psecs->ppsecTail = psec;
  558. psecs->ppsecTail = &psec->psecNext;
  559. DBEXEC(DB_CONLOG, DBPRINT("new psec = %s\n", psec->szName));
  560. csec++;
  561. return(psec);
  562. }
  563. #if DBG
  564. PSEC
  565. PsecFindSectionOfRVA(
  566. DWORD rva,
  567. PSECS psecs
  568. )
  569. /*++
  570. Routine Description:
  571. Determines in which section an RVA lies.
  572. Arguments:
  573. rva - Relative Virtual Address
  574. psecs - Pointer to head of section list
  575. Return Value:
  576. Pointer to SEC, or NULL if RVA could not be mapped to any section.
  577. --*/
  578. {
  579. ENM_SEC enm_sec;
  580. InitEnmSec(&enm_sec, psecs);
  581. while (FNextEnmSec(&enm_sec)) {
  582. PSEC psec = enm_sec.psec;
  583. if ((rva >= psec->rva) && (rva < (psec->rva + psec->cbVirtualSize))) {
  584. break;
  585. }
  586. }
  587. EndEnmSec(&enm_sec);
  588. return(enm_sec.psec);
  589. }
  590. #endif // DBG
  591. PSEC
  592. PsecFindIsec(
  593. SHORT isec,
  594. PSECS psecs
  595. )
  596. /*++
  597. Routine Description:
  598. Determines a section corresponding to the isec.
  599. Arguments:
  600. isec - section number
  601. psecs - Pointer to head of sections list
  602. Return Value:
  603. Pointer to SEC, or NULL if RVA could not be mapped to any section.
  604. --*/
  605. {
  606. static PSEC psec;
  607. ENM_SEC enm_sec;
  608. if (isec <= 0) {
  609. return(NULL);
  610. }
  611. if (psec != NULL) {
  612. // Do a quick test to see if rva is within the last found section
  613. if (psec->isec == isec) {
  614. return(psec);
  615. }
  616. }
  617. InitEnmSec(&enm_sec, psecs);
  618. while (FNextEnmSec(&enm_sec)) {
  619. if (enm_sec.psec->isec == isec) {
  620. break;
  621. }
  622. }
  623. EndEnmSec(&enm_sec);
  624. psec = enm_sec.psec;
  625. return(psec);
  626. }
  627. PSEC
  628. PsecFindNoFlags(
  629. const char *szName,
  630. PSECS psecs)
  631. /*++
  632. Routine Description:
  633. Find a section based on its name.
  634. Arguments:
  635. szName - section name
  636. Return Value:
  637. section if found, NULL otherwise
  638. --*/
  639. {
  640. ENM_SEC enm_sec;
  641. InitEnmSec(&enm_sec, psecs);
  642. while (FNextEnmSec(&enm_sec)) {
  643. if (!strcmp(enm_sec.psec->szName, szName)) {
  644. break;
  645. }
  646. }
  647. EndEnmSec(&enm_sec);
  648. return(PsecApplyMergePsec(enm_sec.psec));
  649. }
  650. PSEC
  651. PsecFind(
  652. PMOD pmod,
  653. const char *szName,
  654. DWORD Characteristics,
  655. PSECS psecs,
  656. PIMAGE_OPTIONAL_HEADER pImgOptHdr)
  657. /*++
  658. Routine Description:
  659. Find a section.
  660. Arguments:
  661. szName - section name
  662. Return Value:
  663. section if found, NULL otherwise
  664. --*/
  665. {
  666. DWORD flags;
  667. BOOL fMatchedName;
  668. ENM_SEC enm_sec;
  669. flags = Characteristics;
  670. ProcessSectionFlags(&flags, szName, pImgOptHdr);
  671. fMatchedName = FALSE;
  672. InitEnmSec(&enm_sec, psecs);
  673. while (FNextEnmSec(&enm_sec)) {
  674. if (!strcmp(enm_sec.psec->szName, szName)) {
  675. if (flags == enm_sec.psec->flagsOrig) {
  676. break;
  677. }
  678. fMatchedName = TRUE;
  679. }
  680. }
  681. EndEnmSec(&enm_sec);
  682. if (fMatchedName && (enm_sec.psec == NULL)) {
  683. const char *sz;
  684. char szBuf[512 + 1];
  685. if (pmod == NULL) {
  686. sz = NULL;
  687. } else {
  688. sz = SzComNamePMOD(pmod, szBuf);
  689. }
  690. Warning(sz, DIFSECATTRIB, szName, Characteristics);
  691. }
  692. return(PsecApplyMergePsec(enm_sec.psec));
  693. }
  694. PSEC
  695. PsecFindGrp(
  696. PMOD pmod,
  697. const char *szName,
  698. DWORD Characteristics,
  699. PSECS psecs,
  700. PIMAGE_OPTIONAL_HEADER pImgOptHdr)
  701. /*++
  702. Routine Description:
  703. Find a section corresponding to a section in a module. This could be
  704. a group. For example, .debug$S.
  705. Arguments:
  706. szName - module section name
  707. Return Value:
  708. section if found, NULL otherwise
  709. --*/
  710. {
  711. const char *szSec;
  712. PSEC psec;
  713. ParseSecName(szName, &szSec);
  714. psec = PsecFind(pmod, szSec, Characteristics, psecs, pImgOptHdr);
  715. if (psec != NULL) {
  716. // Make sure this group actually exists in this section.
  717. if (PgrpFind(psec, szName) != NULL) {
  718. return(psec);
  719. }
  720. }
  721. // We have a group name, but a simple truncation at the '$' didn't produce
  722. // the correct section. Search every section.
  723. ENM_SEC enm_sec;
  724. InitEnmSec(&enm_sec, psecs);
  725. while (FNextEnmSec(&enm_sec)) {
  726. if (PgrpFind(enm_sec.psec, szName) != NULL) {
  727. break;
  728. }
  729. }
  730. EndEnmSec(&enm_sec);
  731. return(enm_sec.psec);
  732. }
  733. void
  734. MergePsec(PSEC psecFrom, PSEC psecInto)
  735. {
  736. PGRP pgrpA;
  737. PGRP pgrpB;
  738. PGRP *ppgrpTail;
  739. // Transfer all GRP's from psecFrom to psecInto.
  740. if (PsecApplyMergePsec(psecFrom) == psecInto) {
  741. // Already merged
  742. return;
  743. }
  744. psecInto = PsecApplyMergePsec(psecInto);
  745. // Merge the GRPs from both sections into a single sorted list
  746. pgrpA = psecFrom->pgrpNext;
  747. pgrpB = psecInto->pgrpNext;
  748. ppgrpTail = &psecInto->pgrpNext;
  749. for (;;) {
  750. int i;
  751. PGRP pgrp;
  752. // Set i < 0: Pick A, i > 0: Pick B
  753. if (pgrpA == NULL) {
  754. if (pgrpB == NULL) {
  755. break;
  756. }
  757. i = 1;
  758. } else if (pgrpB == NULL) {
  759. i = -1;
  760. } else {
  761. i = strcmp(pgrpA->szName, pgrpB->szName);
  762. }
  763. if (i < 0) {
  764. pgrpA->psecBack = psecInto;
  765. pgrp = pgrpA;
  766. pgrpA = pgrpA->pgrpNext;
  767. } else {
  768. pgrp = pgrpB;
  769. pgrpB = pgrpB->pgrpNext;
  770. }
  771. *ppgrpTail = pgrp;
  772. ppgrpTail = &pgrp->pgrpNext;
  773. }
  774. *ppgrpTail = NULL;
  775. psecFrom->pgrpNext = NULL;
  776. // Remember to merge all new GRPs from psecFrom to psecInto
  777. psecFrom->psecMerge = psecInto;
  778. }
  779. void
  780. AppendPsec(PSEC psecFrom, PSEC psecTo)
  781. {
  782. PGRP *ppgrp;
  783. // Transfer all GRP's from psecFrom to psecTo.
  784. if (PsecApplyMergePsec(psecFrom) == psecTo) {
  785. // Already merged
  786. return;
  787. }
  788. psecTo = PsecApplyMergePsec(psecTo);
  789. // Find last GRP in psecTo
  790. ppgrp = &psecTo->pgrpNext;
  791. while (*ppgrp != NULL) {
  792. ppgrp = &(*ppgrp)->pgrpNext;
  793. }
  794. // Attach psecFrom's GRPs to psecTo
  795. *ppgrp = psecFrom->pgrpNext;
  796. // Update backpointer in moved GRPs to point to psecTo
  797. for (; *ppgrp != NULL; ppgrp = &(*ppgrp)->pgrpNext) {
  798. (*ppgrp)->psecBack = psecTo;
  799. }
  800. psecFrom->pgrpNext = NULL;
  801. // Remember to merge all new GRPs from psecFrom to psecTo
  802. psecFrom->psecMerge = psecTo;
  803. }
  804. void
  805. OrderPsecs(PSECS psecs, DWORD dwMask, DWORD dwMatch)
  806. {
  807. PSEC *rgpsec;
  808. WORD isec;
  809. ENM_SEC enmSec;
  810. rgpsec = (PSEC *) PvAlloc(csec * sizeof(PSEC));
  811. for (InitEnmSec(&enmSec, psecs), isec = 0; FNextEnmSec(&enmSec); isec++) {
  812. rgpsec[isec] = enmSec.psec;
  813. }
  814. assert(isec == csec);
  815. psecs->ppsecTail = &psecs->psecHead;
  816. for (isec = 0; isec < csec; isec++) {
  817. if ((rgpsec[isec]->flags & dwMask) != dwMatch) {
  818. continue;
  819. }
  820. *psecs->ppsecTail = rgpsec[isec];
  821. psecs->ppsecTail = &(*psecs->ppsecTail)->psecNext;
  822. }
  823. for (isec = 0; isec < csec; isec++) {
  824. if ((rgpsec[isec]->flags & dwMask) == dwMatch) {
  825. continue;
  826. }
  827. *psecs->ppsecTail = rgpsec[isec];
  828. psecs->ppsecTail = &(*psecs->ppsecTail)->psecNext;
  829. }
  830. *psecs->ppsecTail = NULL;
  831. FreePv(rgpsec);
  832. }
  833. void
  834. SortSectionList(PSECS psecs, int (__cdecl *pfn)(const void *, const void *))
  835. {
  836. PSEC *rgpsec;
  837. WORD isec;
  838. ENM_SEC enmSec;
  839. rgpsec = (PSEC *) PvAlloc(csec * sizeof(PSEC));
  840. for (InitEnmSec(&enmSec, psecs), isec = 0;
  841. FNextEnmSec(&enmSec);
  842. isec++)
  843. {
  844. rgpsec[isec] = enmSec.psec;
  845. }
  846. assert(isec == csec);
  847. qsort(rgpsec, csec, sizeof(PSEC), pfn);
  848. psecs->ppsecTail = &psecs->psecHead;
  849. for (isec = 0; isec < csec; isec++) {
  850. *psecs->ppsecTail = rgpsec[isec];
  851. psecs->ppsecTail = &(*psecs->ppsecTail)->psecNext;
  852. }
  853. *psecs->ppsecTail = NULL;
  854. FreePv(rgpsec);
  855. }
  856. int __cdecl ComparePsecPsecName(const void *ppsec1, const void *ppsec2)
  857. {
  858. PSEC psec1 = *(PSEC *) ppsec1;
  859. PSEC psec2 = *(PSEC *) ppsec2;
  860. return(strcmp(psec1->szName, psec2->szName));
  861. }
  862. void
  863. SortSectionListByName(PSECS psecs)
  864. {
  865. SortSectionList(psecs, ComparePsecPsecName);
  866. }
  867. BOOL
  868. FValidSecName (
  869. const char *szSec
  870. )
  871. {
  872. // Name must not include '$' or blank
  873. return((_tcschr(szSec, '$') == NULL) && (_tcschr(szSec, ' ') == NULL));
  874. }
  875. PLIB
  876. PlibFind(
  877. const char *szName,
  878. PLIB plibHead,
  879. BOOL fIgnoreDir)
  880. // Looks for a library by name.
  881. // If fIgnoreDir, then szName has no directory specified, and we ignore
  882. // the directory when matching it with an existing .lib.
  883. {
  884. ENM_LIB enm_lib;
  885. PLIB plib = NULL;
  886. InitEnmLib(&enm_lib, plibHead);
  887. while (FNextEnmLib(&enm_lib)) {
  888. const char *szLibName;
  889. char szPath[_MAX_PATH];
  890. if (fIgnoreDir && (enm_lib.plib->szName != NULL)) {
  891. char szFname[_MAX_FNAME];
  892. char szExt[_MAX_EXT];
  893. _splitpath(enm_lib.plib->szName, NULL, NULL, szFname, szExt);
  894. strcpy(szPath, szFname);
  895. strcat(szPath, szExt);
  896. szLibName = szPath;
  897. } else {
  898. szLibName = enm_lib.plib->szName;
  899. }
  900. if (szName == NULL && enm_lib.plib->szName == NULL ||
  901. enm_lib.plib->szName && szName && !_ftcsicmp(szLibName, szName))
  902. {
  903. plib = enm_lib.plib;
  904. EndEnmLib(&enm_lib);
  905. break;
  906. }
  907. }
  908. return (plib);
  909. }
  910. PMOD
  911. PmodFind(
  912. PLIB plib,
  913. const char *szName,
  914. DWORD foMember)
  915. /*++
  916. Routine Description:
  917. Find a module.
  918. Arguments:
  919. plib - library to look in
  920. szName - module name
  921. foMember - file offset to member - 0 if object file
  922. Return Value:
  923. module if found, NULL otherwise
  924. --*/
  925. {
  926. ENM_MOD enm_mod;
  927. PMOD pmod = NULL;
  928. InitEnmMod(&enm_mod, plib);
  929. while (FNextEnmMod(&enm_mod)) {
  930. assert(enm_mod.pmod);
  931. if (foMember) {
  932. if (foMember == enm_mod.pmod->foMember) {
  933. pmod = enm_mod.pmod;
  934. EndEnmMod(&enm_mod);
  935. break;
  936. }
  937. } else {
  938. int i;
  939. // Need to do a strcmp() for 68K because of the DUPCON mods
  940. if (fM68K) {
  941. i = strcmp(SzOrigFilePMOD(enm_mod.pmod), szName);
  942. } else {
  943. i = _tcsicmp(SzOrigFilePMOD(enm_mod.pmod), szName);
  944. }
  945. if (!i) {
  946. pmod = enm_mod.pmod;
  947. EndEnmMod(&enm_mod);
  948. break;
  949. }
  950. }
  951. }
  952. return (pmod);
  953. }
  954. STATIC int __cdecl
  955. ComparePCON(
  956. const void *pv1,
  957. const void *pv2)
  958. /*++
  959. Routine Description:
  960. Compare routine for sorting contibutions by module.
  961. Arguments:
  962. pv1 - element 1
  963. pv2 - element 2
  964. Return Value:
  965. < 0 if element 1 < element 2
  966. > 0 if element 1 > element 2
  967. = 0 if element 1 = element 2
  968. --*/
  969. {
  970. assert(pv1);
  971. assert(pv2);
  972. assert(PmodPCON(*(PPCON) pv1));
  973. assert(PmodPCON(*(PPCON) pv2));
  974. return(strcmp(SzObjNamePCON(*(PPCON) pv1), SzObjNamePCON(*(PPCON) pv2)));
  975. }
  976. void
  977. SortPGRPByPMOD(
  978. PGRP pgrp)
  979. /*++
  980. Routine Description:
  981. Sort a group by its module name. This routine is used to handle
  982. idata$* groups. All idata group contributions must be contiguous if
  983. they have similar module names.
  984. Arguments:
  985. pgrp - group to sort
  986. Return Value:
  987. None.
  988. --*/
  989. {
  990. ENM_DST enm_dst;
  991. PPCON rgpcon;
  992. DWORD ipcon;
  993. PCON pcon;
  994. rgpcon = (PPCON) PvAlloc(pgrp->ccon * sizeof(PCON));
  995. ipcon = 0;
  996. InitEnmDst(&enm_dst, pgrp);
  997. while (FNextEnmDst(&enm_dst)) {
  998. pcon = enm_dst.pcon;
  999. rgpcon[ipcon] = pcon;
  1000. ipcon++;
  1001. }
  1002. assert(ipcon == pgrp->ccon);
  1003. qsort((void *) rgpcon, (size_t) pgrp->ccon, sizeof(PCON), ComparePCON);
  1004. for (ipcon = 0; ipcon < (pgrp->ccon - 1); ipcon++) {
  1005. assert(rgpcon[ipcon]);
  1006. assert(rgpcon[ipcon + 1]);
  1007. rgpcon[ipcon]->pconNext = rgpcon[ipcon + 1];
  1008. }
  1009. pgrp->pconNext = rgpcon[0];
  1010. rgpcon[pgrp->ccon - 1]->pconNext = NULL;
  1011. FreePv(rgpcon);
  1012. }
  1013. BOOL
  1014. MoveToEndOfPMODsPCON(
  1015. IN PCON pcon)
  1016. /*++
  1017. Routine Description:
  1018. Move a contribution to the end of a particular contiguous block of
  1019. unique module contributions.
  1020. Arguments:
  1021. pcon - image/driver map contribution
  1022. Return Value:
  1023. None.
  1024. --*/
  1025. {
  1026. PPCON ppconB;
  1027. PCON pconC;
  1028. PCON pconL;
  1029. assert(pcon);
  1030. assert(pcon->pgrpBack);
  1031. // find element before pcon
  1032. ppconB = &(pcon->pgrpBack->pconNext);
  1033. pconC = pcon->pgrpBack->pconNext;
  1034. while (*ppconB != pcon) {
  1035. ppconB = &(pconC->pconNext);
  1036. pconC = pconC->pconNext;
  1037. }
  1038. // find last element with same module name
  1039. pconL = pcon;
  1040. pconC = pcon;
  1041. while (pconC != NULL && !strcmp(SzObjNamePCON(pconL), SzObjNamePCON(pconC))) {
  1042. pconL = pconC;
  1043. pconC = pconC->pconNext;
  1044. }
  1045. // if it is already the last contrib - just ret :azk:
  1046. if (pconL == pcon) {
  1047. return FALSE;
  1048. }
  1049. // swap pcon with pconL
  1050. assert(*ppconB);
  1051. assert(pconL);
  1052. *ppconB = pcon->pconNext;
  1053. pcon->pconNext = pconL->pconNext;
  1054. pconL->pconNext = pcon;
  1055. return TRUE;
  1056. }
  1057. void
  1058. MoveToBeginningOfPGRPsPCON(
  1059. IN PCON pcon)
  1060. /*++
  1061. Routine Description:
  1062. Move a contribution to the beginning of its group
  1063. Arguments:
  1064. pcon - image/driver map contribution
  1065. Return Value:
  1066. None.
  1067. --*/
  1068. {
  1069. PCON pconBack; // One contribution before
  1070. PGRP pgrp;
  1071. assert(pcon);
  1072. pgrp = pcon->pgrpBack;
  1073. assert(pgrp);
  1074. pconBack = pgrp->pconNext;
  1075. // If the pcon is already first in the list, then return. It also
  1076. // takes care of the case where this is the only con in the group
  1077. if (pconBack == pcon) {
  1078. return;
  1079. }
  1080. // find element before pcon
  1081. while (pconBack->pconNext != pcon) {
  1082. pconBack = pconBack->pconNext;
  1083. }
  1084. pconBack->pconNext = pcon->pconNext;
  1085. pcon->pconNext = pgrp->pconNext;
  1086. pgrp->pconNext = pcon;
  1087. }
  1088. void
  1089. MoveToBeginningOfPSECsPGRP(
  1090. IN PGRP pgrp)
  1091. /*++
  1092. Routine Description:
  1093. Move a group to the beginning of its section
  1094. Arguments:
  1095. pgrp - image/driver map grp
  1096. Return Value:
  1097. None.
  1098. --*/
  1099. {
  1100. PGRP pgrpBack; // One group before
  1101. PSEC psec;
  1102. assert(pgrp);
  1103. psec = pgrp->psecBack;
  1104. assert(psec);
  1105. pgrpBack = psec->pgrpNext;
  1106. // If the pgrp is already first in the list, then return. It also
  1107. // takes care of the case where this is the only grp in the section
  1108. if (pgrpBack == pgrp) {
  1109. return;
  1110. }
  1111. // find element before pgrp
  1112. while (pgrpBack->pgrpNext != pgrp) {
  1113. pgrpBack = pgrpBack->pgrpNext;
  1114. }
  1115. pgrpBack->pgrpNext = pgrp->pgrpNext;
  1116. pgrp->pgrpNext = psec->pgrpNext;
  1117. psec->pgrpNext = pgrp;
  1118. }
  1119. void
  1120. MoveToEndPSEC(
  1121. IN PSEC psec,
  1122. IN PSECS psecs)
  1123. /*++
  1124. Routine Description:
  1125. Move a section to the end of the section list.
  1126. Arguments:
  1127. psec - section node in image/driver map to move to the end
  1128. Return Value:
  1129. None.
  1130. --*/
  1131. {
  1132. PPSEC ppsec;
  1133. if (psecs->ppsecTail == &psec->psecNext) {
  1134. assert(psec->psecNext == NULL);
  1135. return; // already last
  1136. }
  1137. // find link to psec
  1138. for (ppsec = &psecs->psecHead; *ppsec != psec;
  1139. ppsec = &(*ppsec)->psecNext)
  1140. {
  1141. assert(*ppsec != NULL); // must find psec
  1142. }
  1143. *ppsec = psec->psecNext; // unhook from list
  1144. *psecs->ppsecTail = psec; // add at end
  1145. psecs->ppsecTail = &psec->psecNext;
  1146. psec->psecNext = NULL; // terminate list
  1147. }
  1148. void
  1149. MoveToBegOfLibPMOD (
  1150. IN PMOD pmod
  1151. )
  1152. /*++
  1153. Routine Description:
  1154. Moves a PMOD to be the first pmod in the list (PLIB).
  1155. Arguments:
  1156. pmod - pointer to mod that needs to be moved.
  1157. Return Value:
  1158. None.
  1159. --*/
  1160. {
  1161. PPMOD ppmodB;
  1162. PMOD pmodC;
  1163. // if it is already the first - return
  1164. if (pmod->plibBack->pmodNext == pmod) {
  1165. return;
  1166. }
  1167. // find pmod before this pmod
  1168. ppmodB = &(pmod->plibBack->pmodNext);
  1169. pmodC = pmod->plibBack->pmodNext;
  1170. while (*ppmodB != pmod) {
  1171. ppmodB = &(pmodC->pmodNext);
  1172. pmodC = pmodC->pmodNext;
  1173. }
  1174. // move pmod to head of list
  1175. assert(*ppmodB);
  1176. *ppmodB = pmod->pmodNext;
  1177. pmod->pmodNext = pmod->plibBack->pmodNext;
  1178. pmod->plibBack->pmodNext = pmod;
  1179. }
  1180. void
  1181. FreePLMODList (
  1182. IN PLMOD *pplmod
  1183. )
  1184. /*++
  1185. Routine Description:
  1186. Frees the list of pmods.
  1187. Arguments:
  1188. pplmod - pointer to list of pmods
  1189. Return Value:
  1190. None.
  1191. --*/
  1192. {
  1193. PLMOD plmod, plmodNext;
  1194. plmod = *pplmod;
  1195. while (plmod) {
  1196. plmodNext = plmod->plmodNext;
  1197. FreePv(plmod);
  1198. plmod = plmodNext;
  1199. }
  1200. (*pplmod) = NULL;
  1201. }
  1202. void
  1203. AddToPLMODList (
  1204. IN PLMOD *pplmod,
  1205. IN PMOD pmod
  1206. )
  1207. /*++
  1208. Routine Description:
  1209. Adds this pmod to list of pmods.
  1210. Arguments:
  1211. pplmod - pointer to list of pmods
  1212. pmod - pmod
  1213. Return Value:
  1214. None.
  1215. --*/
  1216. {
  1217. PLMOD plmod;
  1218. // See if already on list
  1219. if (*pplmod) {
  1220. plmod = *pplmod;
  1221. while (plmod) {
  1222. if (plmod->pmod == pmod) {
  1223. return;
  1224. }
  1225. plmod = plmod->plmodNext;
  1226. }
  1227. }
  1228. // allocate a LMOD
  1229. plmod = (PLMOD) PvAllocZ(sizeof(LMOD));
  1230. // fill in field
  1231. plmod->pmod = pmod;
  1232. // attach it
  1233. if (*pplmod) {
  1234. plmod->plmodNext = *pplmod;
  1235. }
  1236. // update head of list
  1237. (*pplmod) = plmod;
  1238. }
  1239. /*++
  1240. Routine Description:
  1241. Library enumerator definition.
  1242. Arguments:
  1243. None.
  1244. Return Value:
  1245. None.
  1246. --*/
  1247. INIT_ENM(Lib, LIB, (ENM_LIB *penm, PLIB plibHead)) {
  1248. penm->plib = NULL;
  1249. penm->plibHead = plibHead;
  1250. }
  1251. NEXT_ENM(Lib, LIB) {
  1252. if (!penm->plib) {
  1253. penm->plib = penm->plibHead;
  1254. } else {
  1255. penm->plib = penm->plib->plibNext;
  1256. }
  1257. return (penm->plib != NULL);
  1258. }
  1259. END_ENM(Lib, LIB) {
  1260. }
  1261. DONE_ENM
  1262. /*++
  1263. Routine Description:
  1264. Module enumerator definition.
  1265. Arguments:
  1266. None.
  1267. Return Value:
  1268. None.
  1269. --*/
  1270. INIT_ENM(Mod, MOD, (ENM_MOD *penm, PLIB plib)) {
  1271. penm->pmod = NULL;
  1272. penm->plib = plib;
  1273. }
  1274. NEXT_ENM(Mod, MOD) {
  1275. if (penm->plib) {
  1276. if (!penm->pmod) {
  1277. penm->pmod = penm->plib->pmodNext;
  1278. } else {
  1279. penm->pmod = penm->pmod->pmodNext;
  1280. }
  1281. }
  1282. return (penm->pmod != NULL);
  1283. }
  1284. END_ENM(Mod, MOD) {
  1285. }
  1286. DONE_ENM
  1287. /*++
  1288. Routine Description:
  1289. Section enumerator definition.
  1290. Arguments:
  1291. None.
  1292. Return Value:
  1293. None.
  1294. --*/
  1295. INIT_ENM(Sec, SEC, (ENM_SEC *penm, PSECS psecs)) {
  1296. penm->psec = NULL;
  1297. penm->psecHead = psecs->psecHead;
  1298. }
  1299. NEXT_ENM(Sec, SEC) {
  1300. if (!penm->psec) {
  1301. penm->psec = penm->psecHead;
  1302. } else {
  1303. penm->psec = penm->psec->psecNext;
  1304. }
  1305. return (penm->psec != NULL);
  1306. }
  1307. END_ENM(Sec, SEC) {
  1308. }
  1309. DONE_ENM
  1310. /*++
  1311. Routine Description:
  1312. Group enumerator definition.
  1313. Arguments:
  1314. None.
  1315. Return Value:
  1316. None.
  1317. --*/
  1318. INIT_ENM(Grp, GRP, (ENM_GRP *penm, PSEC psec)) {
  1319. penm->pgrp = NULL;
  1320. penm->psec = psec;
  1321. }
  1322. NEXT_ENM(Grp, GRP) {
  1323. if (!penm->pgrp) {
  1324. penm->pgrp = penm->psec->pgrpNext;
  1325. } else {
  1326. penm->pgrp = penm->pgrp->pgrpNext;
  1327. }
  1328. return (penm->pgrp != NULL);
  1329. }
  1330. END_ENM(Grp, GRP) {
  1331. }
  1332. DONE_ENM
  1333. /*++
  1334. Routine Description:
  1335. Source contribution enumerator definition.
  1336. Arguments:
  1337. None.
  1338. Return Value:
  1339. None.
  1340. --*/
  1341. INIT_ENM(Src, SRC, (ENM_SRC *penm, PMOD pmod)) {
  1342. penm->pcon = NULL;
  1343. penm->pmod = pmod;
  1344. penm->icon = 0;
  1345. }
  1346. NEXT_ENM(Src, SRC) {
  1347. if (penm->icon < penm->pmod->ccon) {
  1348. penm->pcon = RgconPMOD(penm->pmod) + penm->icon;
  1349. penm->icon++;
  1350. return(TRUE);
  1351. }
  1352. penm->pcon = NULL;
  1353. return(FALSE);
  1354. }
  1355. END_ENM(Src, SRC) {
  1356. }
  1357. DONE_ENM
  1358. /*++
  1359. Routine Description:
  1360. Destination contribution enumerator definition.
  1361. Arguments:
  1362. None.
  1363. Return Value:
  1364. None.
  1365. --*/
  1366. INIT_ENM(Dst, DST, (ENM_DST *penm, PGRP pgrp)) {
  1367. penm->pcon = NULL;
  1368. penm->pgrp = pgrp;
  1369. }
  1370. NEXT_ENM(Dst, DST) {
  1371. if (!penm->pcon) {
  1372. penm->pcon = penm->pgrp->pconNext;
  1373. } else {
  1374. penm->pcon = penm->pcon->pconNext;
  1375. }
  1376. return (penm->pcon != NULL);
  1377. }
  1378. END_ENM(Dst, DST) {
  1379. }
  1380. DONE_ENM
  1381. #if DBG
  1382. void
  1383. DumpImageMap(
  1384. PSECS psecs)
  1385. /*++
  1386. Routine Description:
  1387. Dump the image map.
  1388. Arguments:
  1389. None.
  1390. Return Value:
  1391. None.
  1392. --*/
  1393. {
  1394. ENM_SEC enm_sec;
  1395. ENM_GRP enm_grp;
  1396. ENM_DST enm_dst;
  1397. DBPRINT("Linker Image Map\n");
  1398. DBPRINT("----------------\n\n");
  1399. InitEnmSec(&enm_sec, psecs);
  1400. while (FNextEnmSec(&enm_sec)) {
  1401. DumpPSEC(enm_sec.psec);
  1402. InitEnmGrp(&enm_grp, enm_sec.psec);
  1403. while (FNextEnmGrp(&enm_grp)) {
  1404. DumpPGRP(enm_grp.pgrp);
  1405. InitEnmDst(&enm_dst, enm_grp.pgrp);
  1406. while (FNextEnmDst(&enm_dst)) {
  1407. DumpPCON(enm_dst.pcon);
  1408. }
  1409. }
  1410. }
  1411. DBPRINT("\n");
  1412. }
  1413. void
  1414. DumpDriverMap(
  1415. PLIB plibHead)
  1416. /*++
  1417. Routine Description:
  1418. Dump the driver map.
  1419. Arguments:
  1420. None.
  1421. Return Value:
  1422. None.
  1423. --*/
  1424. {
  1425. ENM_LIB enm_lib;
  1426. ENM_MOD enm_mod;
  1427. ENM_SRC enm_src;
  1428. DBPRINT("Linker Driver Map\n");
  1429. DBPRINT("-----------------\n\n");
  1430. InitEnmLib(&enm_lib, plibHead);
  1431. while (FNextEnmLib(&enm_lib)) {
  1432. DumpPLIB(enm_lib.plib);
  1433. InitEnmMod(&enm_mod, enm_lib.plib);
  1434. while (FNextEnmMod(&enm_mod)) {
  1435. DumpPMOD(enm_mod.pmod);
  1436. InitEnmSrc(&enm_src, enm_mod.pmod);
  1437. while (FNextEnmSrc(&enm_src)) {
  1438. DumpPCON(enm_src.pcon);
  1439. }
  1440. }
  1441. }
  1442. DBPRINT("\n");
  1443. }
  1444. void
  1445. DumpPSEC(
  1446. PSEC psec)
  1447. /*++
  1448. Routine Description:
  1449. Dump an image section.
  1450. Arguments:
  1451. psec - section to dump.
  1452. Return Value:
  1453. None.
  1454. --*/
  1455. {
  1456. assert(psec);
  1457. DBPRINT("\n==========\n");
  1458. DBPRINT("section=%.8s, isec=%04X\n", psec->szName, psec->isec);
  1459. DBPRINT("rva= %08lX ", psec->rva);
  1460. DBPRINT("foPad= %08lX ", psec->foPad);
  1461. DBPRINT("cbRawData= %08lX ", psec->cbRawData);
  1462. DBPRINT("foRawData= %08lX\n", psec->foRawData);
  1463. DBPRINT("foLinenum= %08lX ", psec->foLinenum);
  1464. DBPRINT("flags= %08lX ", psec->flags);
  1465. DBPRINT("cLinenum= %04X\n", psec->cLinenum);
  1466. fflush(stdout);
  1467. }
  1468. void
  1469. DumpPGRP(
  1470. PGRP pgrp)
  1471. /*++
  1472. Routine Description:
  1473. Dump an image group.
  1474. Arguments:
  1475. pgrp - group to dump.
  1476. Return Value:
  1477. None.
  1478. --*/
  1479. {
  1480. DBPRINT("\n----------\n");
  1481. DBPRINT("\n group=%s\n", pgrp->szName);
  1482. fflush(stdout);
  1483. }
  1484. void
  1485. DumpPLIB(
  1486. PLIB plib)
  1487. /*++
  1488. Routine Description:
  1489. Dump a library.
  1490. Arguments:
  1491. plib - library to dump.
  1492. Return Value:
  1493. None.
  1494. --*/
  1495. {
  1496. DBPRINT("\n==========\n");
  1497. DBPRINT("library=%s\n", plib->szName);
  1498. DBPRINT("foIntMemST=%08lX ", plib->foIntMemSymTab);
  1499. DBPRINT("csymIntMem=%08lX ", plib->csymIntMem);
  1500. DBPRINT("flags= %08lX\n", plib->flags);
  1501. DBPRINT("TimeStamp= %s", ctime((time_t *) &plib->TimeStamp));
  1502. fflush(stdout);
  1503. }
  1504. void
  1505. DumpPMOD(
  1506. PMOD pmod)
  1507. /*++
  1508. Routine Description:
  1509. Dump a module.
  1510. Arguments:
  1511. pmod - module to dump.
  1512. Return Value:
  1513. None.
  1514. --*/
  1515. {
  1516. DBPRINT("\n----------\n");
  1517. DBPRINT(" module=%s, ", SzOrigFilePMOD(pmod));
  1518. if (FIsLibPMOD(pmod)) {
  1519. DBPRINT("foMember=%08lX\n", pmod->foMember);
  1520. } else {
  1521. DBPRINT("szNameMod=%s\n", pmod->szNameMod);
  1522. }
  1523. DBPRINT("foSymTable=%08lX ", pmod->foSymbolTable);
  1524. DBPRINT("csymbols= %08lX ", pmod->csymbols);
  1525. DBPRINT("cbOptHdr= %08lX\n", pmod->cbOptHdr);
  1526. DBPRINT("flags= %08lX ", pmod->flags);
  1527. DBPRINT("ccon= %08lX ", pmod->ccon);
  1528. DBPRINT("icon= %08lX ", pmod->icon);
  1529. DBPRINT("TimeStamp= %s", ctime((time_t *) &pmod->TimeStamp));
  1530. fflush(stdout);
  1531. }
  1532. void
  1533. DumpPCON(
  1534. PCON pcon)
  1535. /*++
  1536. Routine Description:
  1537. Dump a contribution.
  1538. Arguments:
  1539. pcon - contribution to dump.
  1540. Return Value:
  1541. None.
  1542. --*/
  1543. {
  1544. DBPRINT("\n contributor: flags=%08lX, rva=%08lX, module=%s\n",
  1545. pcon->flags, pcon->rva, SzObjNamePCON(pcon));
  1546. DBPRINT("cbRawData= %08lX ", pcon->cbRawData);
  1547. DBPRINT("foRawDataD=%08lX ", pcon->foRawDataDest);
  1548. DBPRINT("chksum =%08lX ", pcon->chksumComdat);
  1549. DBPRINT("selComdat= %04X\n", pcon->selComdat);
  1550. DBPRINT("cbPad = %04X\n", pcon->cbPad);
  1551. fflush(stdout);
  1552. }
  1553. #endif // DBG