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.

1458 lines
40 KiB

4 years ago
  1. //////////////////////////////////////////////////////////////////////////////
  2. // DBI: Debug Information API Implementation
  3. #include "pdbimpl.h"
  4. #include "dbiimpl.h"
  5. #include "cvexefmt.h"
  6. static inline void szFullPathFromST(ST stName, SZ buf);
  7. #ifdef INSTRUMENTED
  8. void DBI1::DumpSymbolPages()
  9. {
  10. char szBuf[256];
  11. unsigned int iPg;
  12. int ich;
  13. int cPgLoaded=0;
  14. sprintf(szBuf, "\n\n**** Symbol page dump for %s ****\r\n", ppdb1->szPDBName);
  15. OutputDebugString(szBuf);
  16. if (cSymRecPgs == 0)
  17. {
  18. sprintf(szBuf, "(No pages)");
  19. OutputDebugString(szBuf);
  20. return;
  21. }
  22. for (iPg=0, ich=0; iPg < cSymRecPgs; iPg++)
  23. {
  24. // Is page loaded?
  25. if (pbvSymRecPgs->fTestBit(iPg))
  26. {
  27. szBuf[ich++] = 'X';
  28. cPgLoaded++;
  29. }
  30. else
  31. {
  32. szBuf[ich++] = '-';
  33. }
  34. // Output 50 pages per line (200K per line)
  35. if (ich == 49)
  36. {
  37. szBuf[ich++] = '\r';
  38. szBuf[ich++] = '\n';
  39. szBuf[ich++] = '\0';
  40. OutputDebugString(szBuf);
  41. ich = 0;
  42. }
  43. }
  44. if (ich != 0)
  45. {
  46. szBuf[ich++] = '\r';
  47. szBuf[ich++] = '\n';
  48. szBuf[ich++] = '\0';
  49. OutputDebugString(szBuf);
  50. }
  51. sprintf(szBuf, "%d out of %d pages are loaded (%d%%)\r\n", cPgLoaded, cSymRecPgs, (cPgLoaded*100)/cSymRecPgs);
  52. OutputDebugString(szBuf);
  53. }
  54. #endif
  55. #pragma warning(4:4355) // 'this' used in member init list...
  56. DBI1::DBI1(PDB1* ppdb1_, BOOL fWrite_, BOOL fCreate_)
  57. : bufGpmodi(fixBufGpmodi, (void*)this, fWrite_), // don't alloc extra padding for read-only
  58. bufRgpmodi(fixBufBase, (void*)&rgpmodi),
  59. bufSymRecs(!fWrite_, fixSymRecs, this),
  60. bufSC(0, 0, fWrite_), // don't alloc extra padding for read-only
  61. bufSecMap(0, 0, fWrite_) // don't alloc extra padding for read-only
  62. {
  63. ppdb1 = ppdb1_;
  64. fWrite = fWrite_;
  65. fCreate = fCreate_;
  66. pgsiGS = 0;
  67. pgsiPS = 0;
  68. potmTSHead = 0;
  69. potmPCTHead = 0;
  70. #ifdef INSTRUMENTED
  71. log = 0;
  72. #endif
  73. imodMac = 0;
  74. fSCCleared = FALSE;
  75. rgpmodi = (MODI**)bufRgpmodi.Start();
  76. expect(fAlign(rgpmodi));
  77. pbvSymRecPgs = 0;
  78. fUDTOutsideRef = FALSE;
  79. }
  80. #pragma warning(default:4355)
  81. void DBI1::fixBufGpmodi(void* pDbi1, void* pOld, void* pNew)
  82. {
  83. if (pOld && pNew) {
  84. DBI1* pdbi1 = (DBI1*)pDbi1;
  85. CB dcb = (long)pNew - (long)pOld;
  86. for (IMOD imod = 0; imod < pdbi1->imodMac; imod++)
  87. pdbi1->rgpmodi[imod] = (MODI*)((PB)pdbi1->rgpmodi[imod] + dcb);
  88. }
  89. }
  90. void DBI1::fixBufBase(void* pv, void* pvOld, void* pvNew)
  91. {
  92. *(void**)pv = pvNew;
  93. }
  94. BOOL DBI1::fInit()
  95. {
  96. #if defined(INSTRUMENTED)
  97. if (fWrite)
  98. log = LogOpen();
  99. if (log)
  100. LogNoteEvent(log, "DBI", 0, letypeBegin, 0);
  101. #endif
  102. CB cbDbiStream = MSFGetCbStream(ppdb1->pmsf, snDbi);
  103. if (cbDbiStream > 0) {
  104. CB cbdbihdr = sizeof(dbihdr);
  105. OFF off = 0;
  106. if (!MSFReadStream2(ppdb1->pmsf, snDbi, 0, &(dbihdr), &cbdbihdr)) {
  107. ppdb1->setReadError();
  108. return FALSE;
  109. }
  110. off += sizeof(dbihdr);
  111. dassert(cbDbiStream == cbdbihdr + dbihdr.cbGpModi + dbihdr.cbSC +
  112. dbihdr.cbSecMap + dbihdr.cbFileInfo);
  113. if (fWrite && (ppdb1->pdbStream.impv == PDB1::impvVC4)) {
  114. // can't incremental link a vc4 format pdb, we have introduced
  115. // new scheme to track refcounts on promoted global syms - return
  116. // a format error here so that we force a full link and rewrite of
  117. // all of the mods streams
  118. // sps 8/14/95
  119. if (fCreate)
  120. // ok we are rewritting this as a vc 4.1 dbi
  121. ppdb1->pdbStream.impv = PDB1::impv;
  122. else {
  123. ppdb1->setLastError(EC_FORMAT, 0);
  124. return FALSE;
  125. }
  126. }
  127. // read in the gpmodi substream
  128. if (dbihdr.cbGpModi > 0) {
  129. expect(fAlign(dbihdr.cbGpModi));
  130. // load gpmodi
  131. PB pb;
  132. if (ppdb1->pdbStream.impv == PDB1::impvVC2) {
  133. // read in v2 modi into temp table and do initial alloc of
  134. // bufGpmodi which will hold the converted v4 modi
  135. Buffer bufGpV2modi;
  136. PB pbV2;
  137. if (!bufGpmodi.SetInitAlloc(dbihdr.cbGpModi) ||
  138. !bufGpV2modi.Reserve(dbihdr.cbGpModi, &pbV2)) {
  139. ppdb1->setOOMError();
  140. return FALSE;
  141. }
  142. else if (!MSFReadStream2(ppdb1->pmsf, snDbi, off, pbV2, &(dbihdr.cbGpModi))) {
  143. ppdb1->setReadError();
  144. return FALSE;
  145. }
  146. // pass thru v2 modi table and copy/convert into v4 modi table
  147. for (PB pbEnd = bufGpV2modi.End(), pbV2EndRec = ((MODI*)pbV2)->pbV2End();
  148. pbV2 < pbEnd;
  149. pbV2 = pbV2EndRec, pbV2EndRec = ((MODI*)pbV2)->pbV2End())
  150. {
  151. CB cb;
  152. DWORD dwDummy = 0;
  153. #pragma warning(disable:4101)
  154. MODI *pmodiDummy = 0;
  155. // copy up to the missing dwCharacteristics field
  156. bufGpmodi.Append(pbV2,
  157. cb = sizeof(pmodiDummy->pmod) + sizeof(pmodiDummy->sc.isect) +
  158. sizeof(pmodiDummy->sc.off) + sizeof(pmodiDummy->sc.cb));
  159. // insert the missing dwCharacteristics field
  160. bufGpmodi.Append((PB)&dwDummy, sizeof(pmodiDummy->sc.dwCharacteristics));
  161. pbV2 += cb;
  162. // copy the rest of the record
  163. bufGpmodi.Append(pbV2, pbV2EndRec - pbV2);
  164. }
  165. pb = bufGpmodi.Start();
  166. off += dbihdr.cbGpModi;
  167. dbihdr.cbGpModi = bufGpmodi.Size();
  168. }
  169. else {
  170. if (!bufGpmodi.Reserve(dbihdr.cbGpModi, &pb)) {
  171. ppdb1->setOOMError();
  172. return FALSE;
  173. }
  174. else if (!MSFReadStream2(ppdb1->pmsf, snDbi, off, pb, &(dbihdr.cbGpModi))) {
  175. ppdb1->setReadError();
  176. return FALSE;
  177. }
  178. off += dbihdr.cbGpModi;
  179. }
  180. // build rgpmodi
  181. for (PB pbEnd = bufGpmodi.End(); pb < pbEnd;
  182. pb = ((MODI*)pb)->pbEnd(), imodMac++)
  183. {
  184. expect(fAlign(pb));
  185. MODI* pmodi = (MODI*)pb;
  186. pmodi->pmod = 0;
  187. pmodi->fWritten = FALSE;
  188. pmodi->ifileMac = 0;
  189. pmodi->mpifileichFile = 0;
  190. if (!bufRgpmodi.Append((PB)&pmodi, sizeof pmodi)) {
  191. ppdb1->setOOMError();
  192. return FALSE;
  193. }
  194. expect(fAlign(&(rgpmodi[imodMac])));
  195. assert(rgpmodi[imodMac] == pmodi);
  196. }
  197. }
  198. // read in the Section Contribution substream
  199. if (dbihdr.cbSC > 0) {
  200. expect(fAlign(dbihdr.cbSC));
  201. if (ppdb1->pdbStream.impv == PDB1::impvVC2) {
  202. // Convert VC++ 2.0 SC entries to VC++ 4.0 format
  203. unsigned csc = dbihdr.cbSC / sizeof(SC20);
  204. CB cb = csc * sizeof(SC);
  205. if (!bufSC.Reserve(cb)) {
  206. ppdb1->setOOMError();
  207. return FALSE;
  208. }
  209. pscEnd = (SC *) bufSC.Start();
  210. cb = sizeof(SC20);
  211. while (csc--) {
  212. SC20 sc20;
  213. if (!MSFReadStream2(ppdb1->pmsf, snDbi, off, &sc20, &cb)) {
  214. ppdb1->setReadError();
  215. return FALSE;
  216. }
  217. pscEnd->isect = sc20.isect;
  218. pscEnd->off = sc20.off;
  219. pscEnd->cb = sc20.cb;
  220. pscEnd->dwCharacteristics = 0;
  221. pscEnd->imod = sc20.imod;
  222. off += sizeof(SC20);
  223. pscEnd++;
  224. }
  225. } else {
  226. if (!bufSC.Reserve(dbihdr.cbSC)) {
  227. ppdb1->setOOMError();
  228. return FALSE;
  229. }
  230. if (!MSFReadStream2(ppdb1->pmsf, snDbi, off, bufSC.Start(), &(dbihdr.cbSC))) {
  231. ppdb1->setReadError();
  232. return FALSE;
  233. }
  234. off += dbihdr.cbSC;
  235. pscEnd = (SC*)(bufSC.End());
  236. }
  237. }
  238. // read in the Section Map substream only if we are not writing
  239. if (dbihdr.cbSecMap && !fWrite) {
  240. expect(fAlign(dbihdr.cbSecMap));
  241. if (!bufSecMap.Reserve(dbihdr.cbSecMap)) {
  242. ppdb1->setOOMError();
  243. return FALSE;
  244. }
  245. else if (!MSFReadStream2(ppdb1->pmsf, snDbi, off, bufSecMap.Start(), &(dbihdr.cbSecMap))) {
  246. ppdb1->setReadError();
  247. return FALSE;
  248. }
  249. }
  250. off += dbihdr.cbSecMap;
  251. if (dbihdr.cbFileInfo > 0) {
  252. expect(fAlign(dbihdr.cbFileInfo));
  253. Buffer bufFileInfo;
  254. if (!bufFileInfo.Reserve(dbihdr.cbFileInfo)) {
  255. ppdb1->setOOMError();
  256. return FALSE;
  257. }
  258. else if (!MSFReadStream2(ppdb1->pmsf, snDbi, off, bufFileInfo.Start(), &dbihdr.cbFileInfo)) {
  259. ppdb1->setReadError();
  260. return FALSE;
  261. }
  262. off += dbihdr.cbFileInfo;
  263. reloadFileInfo(bufFileInfo.Start());
  264. }
  265. }
  266. // for now we will completely delete old Mod info from previous builds on
  267. // a dbi creation. later we may want to perform this instead of trying to
  268. // perform any garbage collection.
  269. #pragma message ("todo - temporary clear dbi on create")
  270. if (fCreate && !clearDBI())
  271. return FALSE;
  272. if (fWrite) {
  273. // open the global and public symbol tables
  274. GSI* pgsigs_;
  275. GSI* pgsips_;
  276. if (!OpenGlobals(&pgsigs_) || !OpenPublics(&pgsips_))
  277. return FALSE;
  278. pgsiGS = (GSI1*) pgsigs_;
  279. pgsiPS = (PSGSI1*) pgsips_;
  280. // just allocate the seg descriptor counters
  281. OMFSegMap omfsegmap = {0, 0};
  282. expect(fAlign(sizeof(omfsegmap)));
  283. if (!bufSecMap.Append((PB)&omfsegmap, sizeof(omfsegmap))) {
  284. ppdb1->setOOMError();
  285. return FALSE;
  286. }
  287. }
  288. return TRUE;
  289. }
  290. inline BOOL nullifyStream(MSF* pmsf, SN* psn) {
  291. dassert(psn);
  292. if (*psn == snNil)
  293. return TRUE;
  294. dassert(pmsf);
  295. if (!MSFDeleteStream(pmsf, *psn))
  296. return FALSE;
  297. *psn = snNil;
  298. return TRUE;
  299. }
  300. BOOL DBI1::clearDBI() {
  301. // delete all mod streams
  302. for (IMOD imod = 0; imod < imodMac; imod++) {
  303. MODI* pmodi = rgpmodi[imod];
  304. if (!nullifyStream(ppdb1->pmsf, &pmodi->sn)) {
  305. ppdb1->setWriteError();
  306. return FALSE;
  307. }
  308. }
  309. // delete sym records stream
  310. if (!nullifyStream(ppdb1->pmsf, &dbihdr.snSymRecs) ||
  311. !nullifyStream(ppdb1->pmsf, &dbihdr.snGSSyms) ||
  312. !nullifyStream(ppdb1->pmsf, &dbihdr.snPSSyms))
  313. {
  314. ppdb1->setWriteError();
  315. return FALSE;
  316. }
  317. // commit these changes to recover their free pages
  318. // (Necessary to avoid doubling the pdb size.)
  319. if ((MSFGetCbStream(ppdb1->pmsf, snDbi) != cbNil && !MSFDeleteStream(ppdb1->pmsf, snDbi)) ||
  320. !MSFCommit(ppdb1->pmsf))
  321. {
  322. ppdb1->setWriteError();
  323. return FALSE;
  324. }
  325. // clear out all buffers and tables
  326. imodMac = 0;
  327. bufGpmodi.Clear();
  328. bufRgpmodi.Clear();
  329. bufSC.Clear();
  330. pscEnd = (SC*)bufSC.End();
  331. fSCCleared = TRUE;
  332. return TRUE;
  333. }
  334. inline BOOL DBI1::writeSymRecs() {
  335. expect(fAlign(bufSymRecs.Size()));
  336. if (dbihdr.snSymRecs == snNil) {
  337. dbihdr.snSymRecs = MSFGetFreeSn(ppdb1->pmsf);
  338. if (dbihdr.snSymRecs == snNil){
  339. ppdb1->setLastError(EC_LIMIT);
  340. return FALSE;
  341. }
  342. if (!MSFReplaceStream(ppdb1->pmsf, dbihdr.snSymRecs, bufSymRecs.Start(),
  343. bufSymRecs.Size())) {
  344. ppdb1->setWriteError();
  345. return FALSE;
  346. }
  347. }
  348. else {
  349. // just append whatever is new
  350. CB cb = MSFGetCbStream(ppdb1->pmsf, dbihdr.snSymRecs);
  351. dassert(bufSymRecs.Size() >= cb);
  352. if (!MSFAppendStream(ppdb1->pmsf, dbihdr.snSymRecs, bufSymRecs.Start() + cb,
  353. bufSymRecs.Size() - cb)) {
  354. ppdb1->setWriteError();
  355. return FALSE;
  356. }
  357. }
  358. return TRUE;
  359. }
  360. int __cdecl SCCmp (const void* elem1, const void* elem2)
  361. {
  362. SC* psc1 = (SC*) elem1;
  363. SC* psc2 = (SC*) elem2;
  364. if (psc1->isect != psc2->isect)
  365. return (psc1->isect > psc2->isect) ? 1 : -1;
  366. if (psc1->off != psc2->off)
  367. return (psc1->off > psc2->off) ? 1 : -1;
  368. return 0;
  369. }
  370. BOOL DBI1::fSave()
  371. {
  372. // output the any deferred udt defns from foreign type servers
  373. int doCount = 0;
  374. do {
  375. fUDTOutsideRef = FALSE;
  376. for (OTM *potm = potmTSHead ; potm; potm = potm->pNext) {
  377. if (potm->ptm)
  378. if (!potm->ptm->fPackDeferredUDTDefns())
  379. return FALSE;
  380. }
  381. expect(doCount < 2);
  382. doCount++;
  383. } while (fUDTOutsideRef);
  384. if (
  385. !pgsiGS->fSave(&(dbihdr.snGSSyms)) ||
  386. !pgsiPS->fSave(&(dbihdr.snPSSyms)) ||
  387. !writeSymRecs())
  388. return FALSE;
  389. if (pscEnd) {
  390. // sort entries in the SC
  391. qsort(bufSC.Start(), pscEnd - (SC*)bufSC.Start(), sizeof(SC), SCCmp);
  392. }
  393. // record lengths of the gpmodi and sc substreams in the header and then
  394. // emit the dbi stream
  395. dbihdr.cbGpModi = bufGpmodi.Size();
  396. dbihdr.cbSC = (PB)pscEnd - bufSC.Start();
  397. dbihdr.cbSecMap = bufSecMap.Size();
  398. expect(fAlign(dbihdr.cbGpModi));
  399. expect(fAlign(dbihdr.cbSC));
  400. expect(fAlign(dbihdr.cbSecMap));
  401. // Convert the file info in the gpmodi into sstFileIndex format
  402. // and save that!
  403. Buffer bufFileInfo;
  404. if (!QueryFileInfo(0, &dbihdr.cbFileInfo) ||
  405. !bufFileInfo.Reserve(dbihdr.cbFileInfo) ||
  406. !QueryFileInfo(bufFileInfo.Start(), &dbihdr.cbFileInfo))
  407. return FALSE;
  408. expect(fAlign(sizeof(dbihdr)));
  409. expect(fAlign(dbihdr.cbFileInfo));
  410. if (!MSFReplaceStream(ppdb1->pmsf, snDbi, &dbihdr, sizeof (dbihdr)) ||
  411. !MSFAppendStream(ppdb1->pmsf, snDbi, bufGpmodi.Start(), dbihdr.cbGpModi) ||
  412. !MSFAppendStream(ppdb1->pmsf, snDbi, bufSC.Start(), dbihdr.cbSC) ||
  413. !MSFAppendStream(ppdb1->pmsf, snDbi, bufSecMap.Start(), dbihdr.cbSecMap) ||
  414. !MSFAppendStream(ppdb1->pmsf, snDbi, bufFileInfo.Start(), dbihdr.cbFileInfo)){
  415. ppdb1->setWriteError();
  416. return FALSE;
  417. }
  418. return TRUE;
  419. }
  420. INTV DBI1::QueryInterfaceVersion()
  421. {
  422. return intv;
  423. }
  424. IMPV DBI1::QueryImplementationVersion()
  425. {
  426. return impv;
  427. }
  428. void DBI1:: NoteModCloseForImod(IMOD imod)
  429. {
  430. assert(0 <= imod && imod < imodMac);
  431. MODI *pmodi = rgpmodi[imod];
  432. pmodi->pmod = NULL;
  433. }
  434. IMOD DBI1::imodForModName(SZ_CONST szModule, SZ_CONST szObjFile)
  435. {
  436. if (imodMac == 0)
  437. return imodNil;
  438. // performance heuristic: search for module starting from last search
  439. // index, rather than from 0.
  440. static IMOD imodLast = imodNil;
  441. if (imodLast == imodNil || imodLast >= imodMac)
  442. imodLast = 0;
  443. IMOD imod = imodLast;
  444. do {
  445. assert(0 <= imod && imod < imodMac);
  446. MODI* pmodi = rgpmodi[imod];
  447. if (_tcsicmp(pmodi->szModule(), szModule) == 0 &&
  448. (!szObjFile || _tcsicmp(pmodi->szObjFile(), szObjFile) == 0))
  449. return imodLast = imod;
  450. imod = (imod + 1) % imodMac;
  451. } while (imod != imodLast);
  452. return imodNil;
  453. }
  454. BOOL DBI1::OpenMod(SZ_CONST szModule, SZ_CONST szObjFile, OUT Mod** ppmod)
  455. {
  456. dassert(szModule);
  457. dassert(ppmod);
  458. IMOD imod = imodForModName(szModule, szObjFile);
  459. if (imod == imodNil) {
  460. if (!fCheckReadWriteMode(TRUE))
  461. return FALSE;
  462. dassert(szObjFile);
  463. MODI* pmodi = new (bufGpmodi, szModule, szObjFile) MODI(szModule, szObjFile);
  464. if (!pmodi)
  465. return FALSE;
  466. if (!bufRgpmodi.Append((PB)&pmodi, sizeof pmodi))
  467. return FALSE;
  468. imod = imodMac++;
  469. expect(fAlign(&(rgpmodi[imod])));
  470. assert(pmodiForImod(imod) == pmodi);
  471. }
  472. return openModByImod(imod, ppmod);
  473. }
  474. BOOL DBI1::openModByImod(IMOD imod, OUT Mod** ppmod)
  475. {
  476. if (imod == imodNil || imod >= imodMac)
  477. return FALSE;
  478. MODI* pmodi = pmodiForImod(imod);
  479. if (!pmodi->pmod) {
  480. // module is not yet "open"...open it
  481. Mod1* pmod_;
  482. if (!(pmod_ = new (ppdb1) Mod1(ppdb1, this, imod)))
  483. return FALSE;
  484. if (!(pmod_->fInit()))
  485. return FALSE;
  486. pmodi->pmod = (Mod*) pmod_;
  487. }
  488. else {
  489. // must not reopen a module if writing
  490. assert(!fWrite);
  491. }
  492. *ppmod = pmodi->pmod;
  493. return TRUE;
  494. }
  495. BOOL DBI1::DeleteMod(SZ_CONST szModule)
  496. {
  497. dassert(szModule);
  498. #pragma message("TODO return FALSE when implemented")
  499. return TRUE;
  500. }
  501. #if 0 // NYI
  502. BOOL DBI1::QueryCountMod(long *pcMod)
  503. {
  504. assert(pcMod);
  505. *pcMod = imodMac;
  506. return TRUE;
  507. }
  508. #endif
  509. BOOL DBI1::QueryNextMod(Mod* pmod, Mod** ppmodNext)
  510. {
  511. MODI* pmodi;
  512. IMOD imod = (IMOD)-1;
  513. // establish imod to be the imod of pmod
  514. if (pmod) {
  515. if (imodLast != imodNil &&
  516. !!(pmodi = pmodiForImod(imodLast)) && pmodi->pmod == pmod) {
  517. // cache hit
  518. imod = imodLast;
  519. }
  520. else {
  521. // cache miss, search MODI table for it
  522. for (imod = 0; imod < imodMac; imod++)
  523. if (!!(pmodi = pmodiForImod(imod)) && pmodi->pmod == pmod)
  524. break;
  525. if (imod >= imodMac) {
  526. ppdb1->setUsageError();
  527. return FALSE;
  528. }
  529. }
  530. }
  531. // at this point, imod address the previous modi, or -1.
  532. // advance to the next modi, if any
  533. if (++imod < imodMac) {
  534. if (!openModByImod(imod, ppmodNext))
  535. return FALSE;
  536. imodLast = imod; // update cache
  537. }
  538. else {
  539. // no more modules; return success but no symbol
  540. *ppmodNext = 0;
  541. }
  542. return TRUE;
  543. }
  544. BOOL DBI1::OpenGlobals(OUT GSI** ppgsi)
  545. {
  546. dassert (ppgsi);
  547. if (pgsiGS) {
  548. // already opened - just return
  549. *ppgsi = pgsiGS;
  550. return TRUE;
  551. }
  552. TPI* ptpi;
  553. if (!ppdb1->OpenTpi(fWrite ? pdbWrite : pdbRead, &ptpi))
  554. return FALSE;
  555. GSI1* pgsi = new GSI1(ppdb1, this, ptpi);
  556. if (!pgsi) {
  557. ppdb1->setOOMError();
  558. return FALSE;
  559. }
  560. if (pgsi->fInit(dbihdr.snGSSyms)) {
  561. *ppgsi = pgsiGS = pgsi;
  562. return TRUE;
  563. }
  564. return FALSE;
  565. }
  566. #pragma message("TODO: lots of ERRRRORS setting via CreateDBI")
  567. BOOL DBI1::OpenPublics(OUT GSI** ppgsi)
  568. {
  569. dassert (ppgsi);
  570. if (pgsiPS) {
  571. // already opened - just return
  572. *ppgsi = pgsiPS;
  573. return TRUE;
  574. }
  575. TPI* ptpi;
  576. if (!ppdb1->OpenTpi(fWrite ? pdbWrite : pdbRead, &ptpi))
  577. return FALSE;
  578. PSGSI1* ppsgsi = new PSGSI1(ppdb1, this, ptpi, fWrite);
  579. if (!ppsgsi) {
  580. ppdb1->setOOMError();
  581. return FALSE;
  582. }
  583. if (ppsgsi->fInit(dbihdr.snPSSyms)) {
  584. *ppgsi = pgsiPS = ppsgsi;
  585. return TRUE;
  586. }
  587. return FALSE;
  588. }
  589. BOOL DBI1::AddSec(ISECT isect, USHORT flags, OFF off, CB cb)
  590. {
  591. if (!fWrite) {
  592. ppdb1->setUsageError();
  593. return FALSE;
  594. }
  595. OMFSegMapDesc* pOMFSegMapDesc;
  596. if (!bufSecMap.Reserve(sizeof(OMFSegMapDesc), (PB*) &pOMFSegMapDesc)) {
  597. ppdb1->setOOMError();
  598. return FALSE;
  599. }
  600. pOMFSegMapDesc->flags = flags;
  601. pOMFSegMapDesc->ovl = 0;
  602. pOMFSegMapDesc->group = 0;
  603. pOMFSegMapDesc->frame = isect;
  604. pOMFSegMapDesc->iSegName = 0xffff;
  605. pOMFSegMapDesc->iClassName = 0xffff;
  606. pOMFSegMapDesc->offset = off;
  607. pOMFSegMapDesc->cbSeg = cb;
  608. OMFSegMap* pOMFSegMap = (OMFSegMap*)bufSecMap.Start();
  609. dassert(pOMFSegMap);
  610. pOMFSegMap->cSeg++;
  611. pOMFSegMap->cSegLog++;
  612. return TRUE;
  613. }
  614. BOOL DBI1::AddPublic(SZ_CONST szPublic, ISECT isect, OFF off)
  615. {
  616. MP* pmp = (MP*) new (ppdb1, szPublic) MP(szPublic, isect, off);
  617. if (!pmp)
  618. return FALSE;
  619. BOOL fOK = packSymToPS((PSYM)pmp);
  620. delete pmp;
  621. return fOK;
  622. }
  623. BOOL DBI1::QuerySecMap(OUT PB pb, CB* pcb)
  624. {
  625. if (!bufSecMap.Start())
  626. return FALSE;
  627. dassert(pcb);
  628. *pcb = bufSecMap.Size();
  629. if (pb) {
  630. memcpy (pb, bufSecMap.Start(), *pcb);
  631. }
  632. return TRUE;
  633. }
  634. BOOL DBI1::QueryModFromAddr(ISECT isect, OFF off, OUT Mod** ppmod,
  635. OUT ISECT* pisect, OUT OFF* poff, OUT CB* pcb)
  636. {
  637. SC* pscLo = (SC*) bufSC.Start();
  638. SC* pscHi = pscEnd;
  639. SC* psc;
  640. // binary search for containing SC
  641. while (pscLo < pscHi) {
  642. psc = pscLo + ((pscHi - pscLo) / 2);
  643. int iResult = psc->IsAddrInSC(isect, off);
  644. if (iResult < 0 )
  645. pscHi = psc;
  646. else if (iResult > 0)
  647. pscLo = psc + 1;
  648. else {
  649. // we found it
  650. BOOL fOK = TRUE;
  651. if (ppmod)
  652. fOK = openModByImod(psc->imod, ppmod);
  653. if (pisect) *pisect = psc->isect;
  654. if (poff) *poff = psc->off;
  655. if (pcb) *pcb = psc->cb;
  656. return fOK;
  657. }
  658. }
  659. return FALSE;
  660. }
  661. inline int SC::IsAddrInSC(ISECT isect_, OFF off_)
  662. {
  663. if (isect == isect_) {
  664. if (off_ < off)
  665. return -1;
  666. if (off_ < off + cb)
  667. return 0;
  668. return 1;
  669. }
  670. else
  671. return (isect_ - isect);
  672. }
  673. BOOL DBI1::Close()
  674. {
  675. if (fWrite && !fSave())
  676. return FALSE;
  677. delete this;
  678. return TRUE;
  679. }
  680. DBI1::~DBI1()
  681. {
  682. #if defined(INSTRUMENTED)
  683. if (log) {
  684. LogNoteEvent(log, "DBI", 0, letypeEvent,
  685. "cModules:%d cSymbols:%d cTypesMapped:%d",
  686. info.cModules, info.cSymbols, info.cTypesMapped);
  687. LogNoteEvent(log, "DBI", 0, letypeEvent,
  688. "cTypesMappedRec.:%d cTypesQueried:%d cTypesAdded:%d",
  689. info.cTypesMappedRecursively, info.cTypesQueried, info.cTypesAdded);
  690. LogNoteEvent(log, "DBI", 0, letypeEvent, "cTMTS:%d cTMR:%d cTMPCT:%d",
  691. info.cTMTS, info.cTMR, info.cTMPCT);
  692. LogNoteEvent(log, "DBI", 0, letypeEnd, 0);
  693. LogClose(log);
  694. }
  695. #endif
  696. #ifdef INSTRUMENTED
  697. DumpSymbolPages();
  698. #endif
  699. if (potmTSHead)
  700. delete potmTSHead;
  701. if (potmPCTHead)
  702. delete potmPCTHead;
  703. // dtor pmodi's
  704. for (IMOD imod = 0; imod < imodMac; imod++) {
  705. MODI* pmodi = pmodiForImod(imod);
  706. if (pmodi)
  707. pmodi->~MODI();
  708. }
  709. if (pbvSymRecPgs)
  710. delete pbvSymRecPgs;
  711. }
  712. // Get a TMTS for the TypeServer PDB referenced by the lfTypeServer record.
  713. // Return this TMTS in *ptm, except (*ptm == 0) when the referenced PDB
  714. // corresponds to the project (output) PDB. Return TRUE if successful.
  715. //
  716. // Note that subsequent calls upon fGetTmts, for the same PDB, from subsequent
  717. // modules in this DBI, will return the same TMTS.
  718. //
  719. BOOL DBI1::fGetTmts(lfTypeServer* pts, SZ_CONST szObjFile, TM** pptm)
  720. {
  721. dassert(pts && pptm);
  722. // Consult the open TMTS list to determine if an existing TMTS matches the
  723. // referenced PDB.
  724. if (fFindTm(potmTSHead, (ST)pts->name, pts->signature, pptm))
  725. return TRUE;
  726. // open a TMTS
  727. if (!fOpenTmts(pts, szObjFile, pptm))
  728. return FALSE;
  729. // add this TMTS the open TMTS list
  730. SZ szName = szCopySt((ST)pts->name);
  731. if (!szName ||
  732. !(potmTSHead = new OTM(potmTSHead, szName, pts->signature, *pptm)))
  733. {
  734. ppdb1->setOOMError();
  735. return FALSE;
  736. }
  737. return TRUE;
  738. }
  739. // Open the TypeServer referenced by *pts and initialize a TMTS from it.
  740. // Set *ptm and return TRUE if successful, FALSE otherwise.
  741. //
  742. BOOL DBI1::fOpenTmts(lfTypeServer* pts, SZ_CONST szObjFile, TM** pptm)
  743. {
  744. #pragma message("TODO - DBCS")
  745. *pptm = 0; // 0 means use 'to' PDB
  746. char szPDBTo[_MAX_PATH];
  747. ppdb1->QueryPDBName(szPDBTo);
  748. if (_strnicmp(szPDBTo, (char*)(pts->name + 1), *(PB)pts->name) == 0) {
  749. // PDB filenames match, reference to the 'to' PDB
  750. return TRUE;
  751. }
  752. char szPDBFrom[_MAX_PATH];
  753. strncpy(szPDBFrom, (char*)(pts->name + 1), *(PB)pts->name);
  754. szPDBFrom[*(PB)pts->name] = 0;
  755. if (pts->signature == ppdb1->QuerySignature() && pts->age <= ppdb1->QueryAge()) {
  756. // PDB signature and age match; this 'from' PDB must contain equivalent
  757. // information (even if it is a copy on some other path). However, we
  758. // may have the highly unlikely case of distinct PDBs with equal
  759. // signatures; to feel better about this case, we won't conclude
  760. // equivalence unless the PDB base names also match. In practice this
  761. // should be exactly conservative enough to avoid false positives and
  762. // yet prevent accidental reopening of the 'to' PDB.
  763. #pragma message("TODO: DBCS review")
  764. char* pchBaseFrom = strrchr(szPDBFrom, '\\'); // REVIEW: international?
  765. char* pchBaseTo = strrchr(szPDBTo, '\\');
  766. if (_tcsicmp(pchBaseFrom, pchBaseTo) == 0) {
  767. // even the base names match; reference to the 'to' PDB
  768. return TRUE;
  769. }
  770. }
  771. // Alas, probably a reference to a different type server. Open it.
  772. EC ec;
  773. char szError[cbErrMax];
  774. PDB* ppdbFrom;
  775. char szPathBuf[_MAX_PATH+_MAX_DRIVE];
  776. char szFullPath[_MAX_PATH+_MAX_DRIVE];
  777. _fullpath(szFullPath, szObjFile, _MAX_PATH+_MAX_DRIVE);
  778. _splitpath(szFullPath, szPathBuf, szPathBuf + _MAX_DRIVE, NULL, NULL);
  779. SZ szPath;
  780. if (szPathBuf[0] == 0) {
  781. // no drive spec - set up path without it
  782. szPath = szPathBuf + _MAX_DRIVE;
  783. }
  784. else {
  785. // concatenate drive and dir to form full path
  786. szPathBuf[2] = szPathBuf[1];
  787. szPathBuf[1] = szPathBuf[0];
  788. szPath = szPathBuf + 1;
  789. }
  790. if (!PDB::OpenValidate(szPDBFrom, szPath, ppdb1->fFullBuild ? (pdbRead pdbGetRecordsOnly pdbFullBuild) :(pdbRead pdbGetRecordsOnly),
  791. pts->signature, pts->age, &ec, szError, &ppdbFrom)) {
  792. ppdb1->setLastError(ec, szError);
  793. return FALSE;
  794. }
  795. // Check again that the PDB we found along the lib path is the same as the
  796. // target PDB.
  797. ppdbFrom->QueryPDBName(szPDBFrom);
  798. if (_tcsicmp(szPDBTo, szPDBFrom) == 0) {
  799. // PDB filenames match, reference to the 'to' PDB
  800. ppdbFrom->Close();
  801. return TRUE;
  802. }
  803. // Create and initialize the TMTS.
  804. TMTS* ptmts = new TMTS(ppdb1, this, ppdb1->ptpi1);
  805. if (!ptmts) {
  806. ppdb1->setOOMError();
  807. return FALSE;
  808. }
  809. if (!ptmts->fInit(ppdbFrom))
  810. return FALSE;
  811. *pptm = ptmts;
  812. return TRUE;
  813. }
  814. BOOL DBI1::fGetTmpct(lfPreComp* ppc, TMPCT** pptmpct)
  815. {
  816. dassert(ppc && pptmpct);
  817. // Consult the open TMPCT list to determine which existing TMPCT corresponds
  818. // to the given module name and signature.
  819. return fFindTm(potmPCTHead, (ST)ppc->name, ppc->signature, (TM**)pptmpct, TRUE);
  820. }
  821. BOOL DBI1::fAddTmpct(lfEndPreComp* pepc, SZ_CONST szModule_, TMPCT* ptmpct)
  822. {
  823. SZ szLocal = new char[_MAX_PATH];
  824. if (!szLocal ||
  825. !_fullpath(szLocal, szModule_, _MAX_PATH) ||
  826. !(potmPCTHead = new OTM(potmPCTHead, szLocal, pepc->signature, (TM*)ptmpct))) {
  827. ppdb1->setOOMError();
  828. return FALSE;
  829. }
  830. return TRUE;
  831. }
  832. BOOL DBI1::fAddTmpct(SZ_CONST szModule_, SZ_CONST szInternalName, TM* ptm)
  833. {
  834. SZ szLocal = new char[_MAX_PATH];
  835. // make sure we have the external & internal name
  836. if (!szLocal ||
  837. !_fullpath(szLocal, szModule_, _MAX_PATH) ||
  838. !szInternalName) {
  839. ppdb1->setOOMError();
  840. return FALSE;
  841. }
  842. // local and internal pct obj names match - nothing to do
  843. if (_tcsicmp(szLocal, szInternalName) == 0)
  844. return TRUE;
  845. // find the potm that matches with the external filename
  846. OTM *potm = potmPCTHead;
  847. for ( ; potm; potm = potm->pNext) {
  848. if ( potm->signature == ((TMR *)ptm)->Sig() &&
  849. _tcsicmp(potm->szName, szLocal) == 0){
  850. break;
  851. }
  852. }
  853. // add a potm (alias) with the internal name
  854. if (potm &&
  855. !(potmPCTHead = new OTM(potmPCTHead, (char *)szInternalName, potm->signature, potm->ptm, TRUE))) {
  856. ppdb1->setOOMError();
  857. return FALSE;
  858. }
  859. return TRUE;
  860. }
  861. // Search this OTM and the rest of the OTM list it heads for one which
  862. // matches the name and signature. If found, set *pptm to the corresponding
  863. // TM and return TRUE, else FALSE.
  864. //
  865. BOOL DBI1::fFindTm(OTM* potm, ST stName, SIG signature, TM** pptm, BOOL fCanonName)
  866. {
  867. // canonilize to a full path name for comparisons
  868. char rgbBuffer[_MAX_PATH + 1];
  869. if (fCanonName)
  870. szFullPathFromST(stName, rgbBuffer);
  871. else {
  872. memcpy(rgbBuffer, stName + 1, *(PB)stName);
  873. rgbBuffer[*(PB)stName] = 0;
  874. }
  875. for ( ; potm; potm = potm->pNext) {
  876. if (potm->signature == signature &&
  877. _tcsicmp(potm->szName, rgbBuffer) == 0)
  878. {
  879. *pptm = potm->ptm;
  880. return TRUE;
  881. }
  882. }
  883. return FALSE;
  884. }
  885. OTM::OTM(OTM* pNext_, SZ szName_, SIG signature_, TM* ptm_, BOOL fAlias_)
  886. : pNext(pNext_), szName(szName_), signature(signature_), ptm(ptm_), fAlias(fAlias_)
  887. {
  888. }
  889. OTM::~OTM()
  890. {
  891. if (szName)
  892. freeSz(szName);
  893. if (fAlias && pNext) {// alias node
  894. delete pNext;
  895. return;
  896. }
  897. if (ptm)
  898. ptm->endDBI();
  899. if (pNext)
  900. delete pNext;
  901. }
  902. void DBI1::fixSymRecs (void* pdbi, void* pOld, void* pNew)
  903. {
  904. DBI1* pdbi1 = (DBI1*)pdbi;
  905. if (pdbi1->pgsiGS)
  906. pdbi1->pgsiGS->fixSymRecs(pOld, pNew);
  907. if (pdbi1->pgsiPS)
  908. pdbi1->pgsiPS->fixSymRecs(pOld, pNew);
  909. }
  910. BOOL DBI1::fReadSymRecPage (unsigned int iPg) {
  911. assert(iPg < cSymRecPgs);
  912. // page already read in
  913. if (pbvSymRecPgs->fTestBit(iPg))
  914. return TRUE;
  915. // Calculate the offset for the start of page.
  916. // We must commit the virtual memory for this page if bufSymRecs is
  917. // using virtual memory (if not this is a noop).
  918. OFF off = iPg * cbPage;
  919. bufSymRecs.Commit(bufSymRecs.Start() + off, cbPage);
  920. // compute size to read in & read in the chunk of sym recs
  921. CB cb;
  922. if (iPg == cSymRecPgs - 1) { // last page?
  923. cb = MSFGetCbStream(ppdb1->pmsf, dbihdr.snSymRecs) % cbPage;
  924. cb = cb ? cb : cbPage;
  925. } else {
  926. cb = cbPage;
  927. }
  928. CB cbRead = cb;
  929. if (!(MSFReadStream2(ppdb1->pmsf, dbihdr.snSymRecs, off, bufSymRecs.Start() + off,
  930. &cbRead)) && cbRead != cb) {
  931. ppdb1->setReadError();
  932. return FALSE;
  933. }
  934. // mark page as read in
  935. pbvSymRecPgs->fSetBit(iPg);
  936. return TRUE;
  937. }
  938. BOOL DBI1::fpsymFromOff(OFF off, PSYM *ppsym)
  939. {
  940. *ppsym = (PSYM)(bufSymRecs.Start() + off);
  941. return fReadSymRec(*ppsym);
  942. }
  943. BOOL DBI1::fReadSymRec (PSYM psym) {
  944. // no sym recs were ever loaded
  945. if (!pbvSymRecPgs)
  946. return TRUE;
  947. // if psym is not part of lazy load area return
  948. if ((PB)psym < bufSymRecs.Start() ||
  949. (PB)psym >= (PB)bufSymRecs.Start() + MSFGetCbStream(ppdb1->pmsf, dbihdr.snSymRecs))
  950. return TRUE;
  951. // read in first page in which sym rec starts
  952. unsigned int iSymRecPgFirst = ((PB)psym - bufSymRecs.Start()) / cbPage;
  953. assert(iSymRecPgFirst < cSymRecPgs);
  954. // If this page is already loaded this is almost a noop
  955. if (!fReadSymRecPage(iSymRecPgFirst))
  956. return FALSE;
  957. // sanity check before we can reference psym->reclen:
  958. // 1) reclen should be the first field in the SYM struct,
  959. // 2) reclen should be two bytes
  960. // 3) both bytes of the reclen field should be in the page we just
  961. // loaded (is it possible to have odd record sizes??)
  962. assert((PB)psym == (PB)&psym->reclen);
  963. assert(sizeof(psym->reclen) == 2);
  964. assert( (UINT)(((PB)psym + 1 - bufSymRecs.Start()) / cbPage) == iSymRecPgFirst);
  965. // make sure we read in all pages that this sym rec spans
  966. unsigned int iSymRecPgLast = (((PB)psym - bufSymRecs.Start()) + psym->reclen
  967. + sizeof(psym->reclen) - 1) / cbPage;
  968. assert(iSymRecPgLast < cSymRecPgs);
  969. unsigned int iPg = iSymRecPgFirst + 1;
  970. for (; iPg <= iSymRecPgLast; iPg++) {
  971. if (!fReadSymRecPage(iPg))
  972. return FALSE;
  973. }
  974. // check for special sym recs S_PROCREF & S_LPROCREF
  975. // - for these we may have to read in more stuff
  976. if ((psym->rectyp == S_PROCREF) || (psym->rectyp == S_LPROCREF)) {
  977. iSymRecPgFirst = (((PB)psym - bufSymRecs.Start()) + psym->reclen
  978. + sizeof(psym->reclen) + 1) / cbPage;
  979. if (!fReadSymRecPage(iSymRecPgFirst))
  980. return FALSE;
  981. iSymRecPgLast = (((PB)psym - bufSymRecs.Start()) + cbForSym(psym) - 1) / cbPage;
  982. iPg = iSymRecPgFirst + 1;
  983. for (; iPg <= iSymRecPgLast; iPg++) {
  984. if (!fReadSymRecPage(iPg))
  985. return FALSE;
  986. }
  987. }
  988. return TRUE;
  989. }
  990. BOOL DBI1::fReadSymRecs()
  991. {
  992. // check and see if we have to read in the Symrecs Stream for this DBI
  993. if (!(bufSymRecs.Start()) && (dbihdr.snSymRecs != snNil)) {
  994. CB cbSymRecs = MSFGetCbStream(ppdb1->pmsf, dbihdr.snSymRecs);
  995. if (cbSymRecs != cbNil){
  996. expect(fAlign(cbSymRecs));
  997. if (!bufSymRecs.Reserve(cbSymRecs)) {
  998. ppdb1->setOOMError();
  999. return FALSE;
  1000. }
  1001. // for full link case simply read in all syms
  1002. if (ppdb1->fFullBuild) {
  1003. CB cbRead = cbSymRecs;
  1004. if (!(MSFReadStream2(ppdb1->pmsf, dbihdr.snSymRecs, 0, bufSymRecs.Start(),
  1005. &cbRead)) && cbRead != cbSymRecs) {
  1006. ppdb1->setReadError();
  1007. return FALSE;
  1008. }
  1009. return TRUE;
  1010. }
  1011. // alloc a bitvec to keep track of pages loaded
  1012. cSymRecPgs = (cbSymRecs + cbPage - 1) / cbPage;
  1013. pbvSymRecPgs = new BITVEC;
  1014. if (!pbvSymRecPgs) {
  1015. ppdb1->setOOMError();
  1016. return FALSE;
  1017. }
  1018. if (!pbvSymRecPgs->fAlloc(cSymRecPgs)) {
  1019. ppdb1->setOOMError();
  1020. return FALSE;
  1021. }
  1022. // we will lazy load sym recs
  1023. return TRUE;
  1024. }
  1025. }
  1026. return TRUE;
  1027. }
  1028. BOOL DBI1::fCheckReadWriteMode(BOOL fWrite_)
  1029. {
  1030. if (fWrite_ != fWrite) {
  1031. ppdb1->setUsageError();
  1032. return FALSE;
  1033. }
  1034. else
  1035. return TRUE;
  1036. }
  1037. BOOL DBI1::addSecContrib(SC& scIn)
  1038. {
  1039. if (!fWrite)
  1040. return FALSE;
  1041. #pragma message("Steve: please review with me. -Jan")
  1042. if (((PB)pscEnd == bufSC.End()) &&
  1043. (!bufSC.Reserve(sizeof(SC), (PB*)&pscEnd))) {
  1044. ppdb1->setOOMError();
  1045. return FALSE;
  1046. }
  1047. expect(fAlign(pscEnd));
  1048. *pscEnd = scIn;
  1049. pscEnd++;
  1050. dassert((PB)(pscEnd) <= bufSC.End());
  1051. return TRUE;
  1052. }
  1053. BOOL DBI1::invalidateSCforMod(IMOD imod) {
  1054. if (fSCCleared)
  1055. return TRUE; // the SC was cleared when the DBI was open - do nothing
  1056. // scan the SC looking for matching imods and invalidate the entry
  1057. for (SC* psc = (SC*) bufSC.Start();
  1058. psc < pscEnd;
  1059. )
  1060. {
  1061. expect(fAlign(psc));
  1062. if (psc->imod == imod) {
  1063. // move bottom of the table into this spot
  1064. dassert ((PB)pscEnd > bufSC.Start())
  1065. *psc = *(--pscEnd);
  1066. }
  1067. else
  1068. psc++;
  1069. }
  1070. return TRUE;
  1071. }
  1072. BOOL DBI1::initFileInfo(IMOD imod, IFILE ifileMac)
  1073. {
  1074. MODI* pmodi = pmodiForImod(imod);
  1075. if (!pmodi)
  1076. return FALSE;
  1077. if (ifileMac > pmodi->ifileMac) {
  1078. // need more space than we currently have
  1079. if (!(pmodi->mpifileichFile = new ICH[ifileMac]))
  1080. return FALSE;
  1081. }
  1082. pmodi->ifileMac = ifileMac;
  1083. memset(pmodi->mpifileichFile, 0, ifileMac * sizeof(ICH));
  1084. return TRUE;
  1085. }
  1086. BOOL DBI1::addFileInfo(IMOD imod, IFILE ifile, ST stFile)
  1087. {
  1088. MODI* pmodi = pmodiForImod(imod);
  1089. if (!pmodi)
  1090. return FALSE;
  1091. ICH ich;
  1092. if (!addFilename(stFile, &ich))
  1093. return FALSE;
  1094. pmodi->mpifileichFile[ifile] = ich;
  1095. return TRUE;
  1096. }
  1097. BOOL DBI1::addFilename(ST stFile, ICH *pich)
  1098. {
  1099. // search bufFilenames, the catenation of filenames, for szFile
  1100. for (ST st = (ST)bufFilenames.Start(), stEnd = (ST)bufFilenames.End(); st < stEnd; st += cbForSt(st)) {
  1101. if (memcmp(st, stFile, cbForSt(st)) == 0) {
  1102. // found
  1103. *pich = st - (ST)bufFilenames.Start();
  1104. return TRUE;
  1105. }
  1106. }
  1107. // not found: append the new name
  1108. *pich = bufFilenames.Size();
  1109. if (!bufFilenames.Reserve(cbForSt(stFile), (PB*)&st))
  1110. return FALSE;
  1111. memcpy(st, stFile, cbForSt(stFile));
  1112. return TRUE;
  1113. }
  1114. BOOL DBI1::reloadFileInfo(PB pb)
  1115. {
  1116. if (*((IMOD*&)pb)++ != imodMac)
  1117. return FALSE;
  1118. USHORT cRefs = *((USHORT*&)pb)++;
  1119. USHORT* mpimodiref = (USHORT*)pb;
  1120. USHORT* mpimodcref = (USHORT*)((PB)mpimodiref + sizeof(USHORT)*imodMac);
  1121. ICH* mpirefichFile = (ICH*) ((PB)mpimodcref + sizeof(USHORT)*imodMac);
  1122. PCH rgchNames = (PCH) ((PB)mpirefichFile + sizeof(ICH)*cRefs);
  1123. for (IMOD imod = 0; imod < imodMac; imod++) {
  1124. if (!initFileInfo(imod, mpimodcref[imod]))
  1125. return FALSE;
  1126. for (IFILE ifile = 0; ifile < mpimodcref[imod]; ifile++) {
  1127. UINT iref = mpimodiref[imod] + ifile;
  1128. ICH ich = mpirefichFile[iref];
  1129. if (!addFileInfo(imod, ifile, &rgchNames[ich]))
  1130. return FALSE;
  1131. }
  1132. }
  1133. return TRUE;
  1134. }
  1135. BOOL DBI1::QueryFileInfo(OUT PB pb, CB* pcb)
  1136. {
  1137. debug(PB pbSave = pb);
  1138. // count refs
  1139. int cRefs = 0;
  1140. for (IMOD imod = 0; imod < imodMac; imod++) {
  1141. MODI* pmodi = pmodiForImod(imod);
  1142. if (!pmodi)
  1143. return FALSE;
  1144. cRefs += pmodi->ifileMac;
  1145. }
  1146. CB cb = cbAlign(2*sizeof(USHORT) + 2*sizeof(USHORT)*imodMac + sizeof(ULONG)*cRefs + bufFilenames.Size());
  1147. if (!pb) {
  1148. *pcb = cb;
  1149. return TRUE;
  1150. }
  1151. else if (pb && *pcb != cb)
  1152. return FALSE;
  1153. // form sstFileIndex record
  1154. *((USHORT*&)pb)++ = imodMac;
  1155. *((USHORT*&)pb)++ = cRefs;
  1156. USHORT irefStart = 0;
  1157. for (imod = 0; imod < imodMac; imod++) {
  1158. *((USHORT*&)pb)++ = irefStart;
  1159. irefStart += pmodiForImod(imod)->ifileMac;
  1160. }
  1161. for (imod = 0; imod < imodMac; imod++)
  1162. *((USHORT*&)pb)++ = pmodiForImod(imod)->ifileMac;
  1163. for (imod = 0; imod < imodMac; imod++) {
  1164. MODI* pmodi = pmodiForImod(imod);
  1165. for (IFILE ifile = 0; ifile < pmodi->ifileMac; ifile++)
  1166. *((ICH*&)pb)++ = pmodi->mpifileichFile[ifile];
  1167. }
  1168. memcpy(pb, bufFilenames.Start(), bufFilenames.Size());
  1169. pb += bufFilenames.Size();
  1170. debug(assert(pbSave + cb == (PB) cbAlign((long)pb)));
  1171. return TRUE;
  1172. }
  1173. void DBI1::DumpMods()
  1174. {
  1175. printf("%-20.20s %-30.30s sn cbSyms cbLines cbFpo\n", "module", "file");
  1176. for (IMOD imod = 0; imod < imodMac; imod++) {
  1177. MODI* pmodi = pmodiForImod(imod);
  1178. printf("%-20.20s %-30.30s %3d %6ld %7ld %5ld\n",
  1179. pmodi->szModule(), pmodi->szObjFile(), (short)pmodi->sn,
  1180. pmodi->cbSyms, pmodi->cbLines, pmodi->cbFpo);
  1181. }
  1182. fflush(stdout);
  1183. }
  1184. void DBI1::DumpSecContribs()
  1185. {
  1186. printf("Section Contributions\nisect\toff\t\tcb\t\tdwChar\t\timod\n");
  1187. for (SC* psc=(SC*)(bufSC.Start()); psc < pscEnd; psc++) {
  1188. printf("0x%4.4x\t0x%8.8x\t0x%8.8x\t0x%08lx\t0x%4.4x\n",
  1189. psc->isect, psc->off, psc->cb, psc->dwCharacteristics, psc->imod);
  1190. }
  1191. fflush(stdout);
  1192. }
  1193. void DBI1::DumpSecMap()
  1194. {
  1195. if (!bufSecMap.Start())
  1196. return;
  1197. OMFSegMap* phdr = (OMFSegMap*) bufSecMap.Start();
  1198. printf("Section Map cSeg = 0x%4.4x, cSegLog = 0x%4.4x\n", phdr->cSeg, phdr->cSegLog);
  1199. printf("flags\tovl\tgroup\tframe\tsegname\tclass\toffset\t\tcbseg\n");
  1200. for (OMFSegMapDesc* pDesc =(OMFSegMapDesc*)(bufSecMap.Start() + sizeof (OMFSegMap));
  1201. (PB) pDesc < bufSecMap.End();
  1202. pDesc++) {
  1203. printf("0x%4.4x\t0x%4.4x\t0x%4.4x\t0x%4.4x\t0x%4.4x\t0x%4.4x\t0x%8.8x\t0x%8.8x\n",
  1204. pDesc->flags, pDesc->ovl, pDesc->group, pDesc->frame, pDesc->iSegName,
  1205. pDesc->iClassName, pDesc->offset, pDesc->cbSeg);
  1206. }
  1207. fflush(stdout);
  1208. }
  1209. BOOL DBI1::AddThunkMap(OFF* poffThunkMap, UINT nThunks, CB cbSizeOfThunk,
  1210. SO* psoSectMap, UINT nSects, ISECT isectThunkTable, OFF offThunkTable)
  1211. {
  1212. dassert(pgsiPS);
  1213. return pgsiPS->addThunkMap(poffThunkMap, nThunks, cbSizeOfThunk, psoSectMap, nSects, isectThunkTable, offThunkTable);
  1214. }
  1215. void szFullPathFromST(ST stName, SZ szFullPath)
  1216. {
  1217. char rgbName[_MAX_PATH];
  1218. memcpy(rgbName, stName + 1, *(PB)stName);
  1219. rgbName[*(PB)stName] = 0;
  1220. _fullpath(szFullPath, rgbName, _MAX_PATH);
  1221. }
  1222. BOOL DBI1::QueryTiForUDT(SZ sz, BOOL fCase, OUT TI* pti, OUT TM** pptm)
  1223. {
  1224. static TM* ptmCache = 0;
  1225. if (ptmCache && ptmCache->QueryTiForUDT(sz, fCase, pti)) {
  1226. fUDTOutsideRef = TRUE;
  1227. *pptm = ptmCache;
  1228. return TRUE;
  1229. }
  1230. else {
  1231. for (OTM *potm = potmTSHead ; potm; potm = potm->pNext) {
  1232. if (potm->ptm && potm->ptm->QueryTiForUDT(sz, fCase, pti)) {
  1233. fUDTOutsideRef = TRUE;
  1234. ptmCache = potm->ptm;
  1235. *pptm = ptmCache;
  1236. return TRUE;
  1237. }
  1238. }
  1239. }
  1240. return FALSE;
  1241. }