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.

198 lines
7.5 KiB

4 years ago
  1. //////////////////////////////////////////////////////////////////////////////
  2. // Type map implementation
  3. // Type maps are created and used to map the type indices used by symbols in
  4. // the current module, into type indices corresponding to type records
  5. // stored in the types section of the output PDB.
  6. //
  7. // Type maps are organized according to this class hierarchy:
  8. // TM // abstract base class
  9. // TMTS // TypeServer type map (for "cl /Zi" modules)
  10. // TMR // single-module type record type map (for "cl /Z7" modules)
  11. // TMPCT // precompiled type type map (for "cl /Yc /Z7" modules)
  12. //
  13. // TM lifetimes. Whereas each TMR object is created to pack types for a single
  14. // /Z7 module before its subsequent destruction at Mod1::Close, both TMTS (/Zi) and
  15. // TMPCT (/Yc /Z7) type map objects, once created, are kept alive and associated
  16. // with the current DBI object until DBI1::Close.
  17. //
  18. // For TMTSs, this is done for efficiency: if several modules reference types
  19. // in some other PDB, it would be wasteful to continually open and close that
  20. // PDB and continually remap its types. Consider:
  21. //
  22. // // mod1.cpp // mod2.cpp
  23. // #include "x.h" #include "x.h"
  24. // X x1; X x2;
  25. //
  26. // // Generated CV information (/Zi):
  27. // mod1.obj: mod2.obj:
  28. // symbols: symbols:
  29. // S_GDATA32 x1 ti(X) S_GDATA32 x2 ti(X)
  30. // types: S_GDATA32 p ti(int**)
  31. // LF_TYPESERVER foo.pdb types:
  32. // LF_TYPESERVER foo.pdb
  33. //
  34. // Here if mod1.obj and then mod2.obj are packed using DBI::OpenMod, etc., it
  35. // would be inefficient to open, use, establish a type map for X and the types
  36. // X transitively refers to, and then close foo.pdb, for mod1.obj, only to do
  37. // the same thing over again for mod2.obj. Rather, the TMTS for mod1.obj
  38. // can be completely reused by mod2.obj, which can then further augment the
  39. // type map with additional types (e.g. int** in the example above).
  40. //
  41. //
  42. // In contrast, TMPCTs persist across modules, not for efficiency, but rather
  43. // to ensure a correct packing of modules which use the C7 PCT (precompiled
  44. // types) feature. PCTs arise when the /Yc /Z7 and /Yu /Z7 flags are specified.
  45. // For the /Yc /Z7 ("PCH create"), one module (the "PCT module") is compiled
  46. // and all types it sees are written to its module's .obj's types section.
  47. // For subsequent /Yu /Z7 ("PCH use") modules, a special record referencing
  48. // types in the PCT module is emitted rather than repeating types known to be
  49. // in the PCT module's type information. Thus, a module's symbols may refer to
  50. // type records located in the PCT module rather than the current module's
  51. // type records.
  52. //
  53. // Therefore type information, including raw types and the current partial
  54. // type map, must be retained across modules. Consider:
  55. //
  56. // // pct.cpp // a.cpp // b.cpp
  57. // #include "x.h" #include "x.h" #include "x.h"
  58. // #pragma hdrstop #pragma hdrstop #pragma hdrstop
  59. // #include "y.h" #include "a.h" #include "b.h"
  60. // ... ... ...
  61. //
  62. // // Generated CV info (/Yc /Z7 pct.cpp, /Yu /Z7 a.cpp, /Yu /Z7 b.cpp):
  63. // pct.obj: a.obj: b.obj:
  64. // symbols: symbols: symbols:
  65. // ... ... ...
  66. // types: types: types:
  67. // <0x1000-0x4000> LF_PRECOMP(pct.obj) LF_PRECOMP(pct.obj)
  68. // LF_ENDPRECOMP <0x4001-...> <0x4001-...>
  69. // <0x4001-...>
  70. //
  71. // In the example above, we see that each module contains types with type
  72. // indices (ti's) starting at 0x1000; however a.obj and b.obj's modules
  73. // do not actually contain copies of the types known to be in pct.obj; rather
  74. // they reference those types with a PRECOMP record. Note that pct.obj's
  75. // type 0x4001 is probably different from a.obj's and likewise from b.obj's.
  76. //
  77. // To deal with this kind of module type information, cvpack or link must
  78. // ensure that modules containing LF_ENDPRECOMP are passed to DBI::OpenMod
  79. // and Mod::AddTypes before other modules whose types' LF_PRECOMP's refer
  80. // to PCT modules.
  81. //
  82. // For its part, DBI1 will keep alive (across modules) any TMPCTs that get
  83. // created when types containing LF_ENDPRECOMPs are seen. Thus subsequent
  84. // modules which contain LF_PRECOMP records referencing those types
  85. // (e.g. compiled "cl /Yu /Z7") can simply load these types from their TMPCT.
  86. // Therefore, for modules containing LF_PRECOMP records, we use a TMPCT to help
  87. // initialize each module's TMR.
  88. //
  89. //
  90. // By the way, someday we may elect to further extend the lifetime of TMTS and
  91. // TMPCT type maps to make them persistent across link/cvpack invocations...
  92. class TM { // abstract type map
  93. public:
  94. TM(PDB1* ppdb1To_, DBI1* pdbi1To_, TPI* ptpiTo_);
  95. BOOL fMapRti(TI& rti);
  96. virtual void endMod();
  97. virtual void endDBI();
  98. virtual BOOL IsTMPCT(){return FALSE;}
  99. virtual ~TM() = 0;
  100. virtual BOOL fEliminateUDTs()
  101. {
  102. return FALSE;
  103. }
  104. virtual BOOL fPackDeferredUDTDefns()
  105. {
  106. return TRUE;
  107. }
  108. BOOL fNotOutOfTIs(){return ptpiTo->QueryTiMac() < ::tiMax;};
  109. virtual PTYPE ptypeForTi(TI ti) const pure;
  110. virtual BOOL QueryTiForUDT(char* sz, BOOL fCase, OUT TI* pti) pure;
  111. protected:
  112. BOOL fInit(TI tiMin_, TI tiMac_);
  113. virtual BOOL fMapRti(TI& rti, int depth, BOOL useDefn) = 0;
  114. inline TI& rtiMapped(TI ti) const;
  115. inline TI tiBias(TI ti) const;
  116. inline BOOL isValidTi(TI ti) const;
  117. PDB1* ppdb1To; // 'to' PDB
  118. DBI1* pdbi1To; // 'to' DBI
  119. TPI* ptpiTo; // 'to' TypeServer
  120. TI tiMin; // minimum TI in this module
  121. TI tiMac; // maximum TI in this module + 1
  122. unsigned ctiFrom; // tiBias(tiMac)
  123. TI* mptiti; // memoization of mapping to project PDB TIs
  124. };
  125. class TMTS : public TM { // type map for modules which use a different TypeServer
  126. public:
  127. TMTS(PDB1* ppdb1To_, DBI1* pdbi1To_, TPI* ptpiTo_);
  128. BOOL fInit(PDB* ppdbFrom);
  129. ~TMTS();
  130. BOOL fEliminateUDTs()
  131. {
  132. dassert(ptpiFrom);
  133. return ptpiFrom->SupportQueryTiForUDT();
  134. }
  135. BOOL fPackDeferredUDTDefns();
  136. inline PTYPE ptypeForTi(TI ti) const;
  137. BOOL QueryTiForUDT(char* sz, BOOL fCase, OUT TI* pti);
  138. private:
  139. BOOL fMapRti(TI& rti, int depth, BOOL);
  140. PDB* ppdbFrom; // 'from' PDB
  141. DBI* pdbiFrom; // 'from' DBI
  142. TPI* ptpiFrom; // 'from' TPI
  143. UDTRefs* pUDTRefs; // bit maps to track deferred UDT output
  144. };
  145. class TMR : public TM { // type map for module with type records
  146. public:
  147. TMR(PDB1* ppdb1To_, DBI1* pdbi1To_, TPI* ptpiTo_);
  148. BOOL fInit(PB pbTypes_, CB cb, SZ szModule);
  149. void endMod();
  150. void endDBI();
  151. BOOL IsTMPCT(){return fTMPCT;}
  152. SIG Sig(){return signature;}
  153. ~TMR();
  154. inline PTYPE ptypeForTi(TI ti) const;
  155. BOOL QueryTiForUDT(char* sz, BOOL fCase, OUT TI* pti);
  156. protected:
  157. BOOL fMapRti(TI& rti, int depth, BOOL useDefn);
  158. inline TI& rtiMapped(TI ti) const;
  159. inline TI& rtiDefnMapped(TI ti) const;
  160. PTYPE ptypeCreateFwdRef(PTYPE ptype);
  161. PTYPE ptypeCatenateFieldList(PTYPE ptype);
  162. TMPCT* ptmpct; // (if non-0) type map for PCT types
  163. TI* mptitiDefn; // memoization of mapping /Z7 struct defn TIs
  164. // to project PDB TIs
  165. PTYPE* mptiptype; // mapping from old TI to old type record address
  166. private:
  167. PB pbTypes; // group type records referenced by the PCT's mptiptype
  168. BOOL fTMPCT; // TRUE if PCT
  169. SIG signature; // signature on the TMPCT
  170. };
  171. class TMPCT : public TMR { // type map for a PCT module
  172. public:
  173. TMPCT(PDB1* ppdb1To_, DBI1* pdbi1To_, TPI* ptpiTo_);
  174. BOOL fInit(PB pbTypes_, CB cb, SZ szModule);
  175. void endMod();
  176. void endDBI();
  177. ~TMPCT();
  178. };
  179. struct OTM { // DBI1 helper to find some currently Open TM
  180. OTM(OTM* pNext_, SZ szName, SIG signature, TM* ptm, BOOL fAlias = FALSE);
  181. ~OTM();
  182. OTM* pNext; // next OTM in this list
  183. SIG signature; // signature on this TM
  184. SZ szName; // name of the TM (TMTS: PDB name; TMPCT: module name)
  185. TM* ptm; // TM (TMTS or TMPCT)
  186. BOOL fAlias; // this OTM is an alias for a TMPCT
  187. };