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.

894 lines
24 KiB

4 years ago
  1. // PDBDUMP -- Sample Debug Information API application
  2. // VC++4.0 Read-Only OEM Edition
  3. // Copyright (C) 1993-1995, Microsoft Corp. All Rights Reserved.
  4. //
  5. // Unfinished but still interesting.
  6. // Pardon the Hungarian...
  7. //
  8. #include <stdio.h>
  9. #include <stdarg.h>
  10. #include <afx.h>
  11. #include "oemdbi.h"
  12. typedef SYMTYPE* PSYM;
  13. typedef TYPTYPE* PTYPE;
  14. typedef char* ST; // length prefixed string
  15. BOOL dumpFileInfo(DBI* pdbi);
  16. BOOL dumpGlobals(DBI* pdbi);
  17. BOOL dumpPublics(DBI* pdbi);
  18. BOOL dumpGSI(GSI* pgsi);
  19. void dumpSymsSz(DBI* pdbi, char* sz);
  20. void dumpLinesSz(DBI* pdbi, char* sz);
  21. BOOL dumpSymbols(PB pb, CB cb);
  22. void dumpSymbol(PSYM psym);
  23. void dumpTpiSz(TPI* ptpi, char* sz);
  24. void dumpTypes(TPI* ptpi);
  25. void dumpType(TI ti);
  26. void dumpMod(Mod* pmod);
  27. BOOL dumpLines(PB pb, CB cb);
  28. void dump(PB pb, CB cb, SZ szFmt, ...);
  29. enum Bind { bindPtr, bindArray, bindProc, bindNone };
  30. PDB* ppdb;
  31. TPI* ptpi;
  32. DBI* pdbi;
  33. int main(int argc, char *argv[]) {
  34. if (argc != 2) {
  35. fprintf(stderr, "usage: %s <pdb>\n", argv[0]);
  36. return 1;
  37. }
  38. SZ szPDB = argv[1];
  39. EC ec;
  40. char szErr[cbErrMax];
  41. if (!PDBOpen(szPDB, pdbRead, 0, &ec, szErr, &ppdb))
  42. goto fail1;
  43. if (!PDBOpenTpi(ppdb, pdbRead, &ptpi))
  44. goto fail2;
  45. // dumpTypes(ptpi);
  46. if (!PDBOpenDBI(ppdb, pdbRead, "<target>.exe", &pdbi))
  47. goto fail3;
  48. dumpFileInfo(pdbi);
  49. dumpGlobals(pdbi);
  50. dumpPublics(pdbi);
  51. Mod* pmod;
  52. printf("\nmodules:\nimod name\n");
  53. for (pmod = 0; DBIQueryNextMod(pdbi, pmod, &pmod) && pmod; ) {
  54. char szMod[_MAX_PATH];
  55. CB cb = sizeof(szMod);
  56. IMOD imod;
  57. if (ModQueryName(pmod, szMod, &cb) &&
  58. ModQueryImod(pmod, &imod))
  59. printf("%4d %s\n", imod, szMod);
  60. }
  61. putchar('\n');
  62. for (pmod = 0; DBIQueryNextMod(pdbi, pmod, &pmod) && pmod; ) {
  63. // note it's OK to 'QueryNextMod' an open mod
  64. dumpMod(pmod);
  65. ModClose(pmod);
  66. }
  67. return 0;
  68. fail3:
  69. DBIClose(pdbi);
  70. fail2:
  71. TypesClose(ptpi);
  72. fail1:
  73. PDBClose(ppdb);
  74. return 1;
  75. }
  76. void dumpTypes(TPI* ptpi) {
  77. TI tiMin = TypesQueryTiMin(ptpi);
  78. TI tiMac = TypesQueryTiMac(ptpi);
  79. for (TI ti = tiMin; ti < tiMac; ti++)
  80. dumpType(ti);
  81. }
  82. BOOL dumpFileInfo(DBI* pdbi) {
  83. printf("file info:\n");
  84. CB cb;
  85. PB pb, pbAlloc;
  86. if (!DBIQueryFileInfo(pdbi, 0, &cb) ||
  87. !(pbAlloc = pb = new BYTE[cb]) ||
  88. !DBIQueryFileInfo(pdbi, pb, &cb))
  89. return FALSE;
  90. IMOD imodMac = *((IMOD*&)pb)++;
  91. USHORT cRefs = *((USHORT*&)pb)++;
  92. printf("imodMac:%d cRefs:%d\n", imodMac, cRefs);
  93. typedef char* PCH;
  94. typedef long ICH;
  95. USHORT* mpimodiref = (USHORT*)pb;
  96. USHORT* mpimodcref = (USHORT*)((PB)mpimodiref + sizeof(USHORT)*imodMac);
  97. ICH* mpirefichFile = (ICH*) ((PB)mpimodcref + sizeof(USHORT)*imodMac);
  98. PCH rgchNames = (PCH) ((PB)mpirefichFile + sizeof(ICH)*cRefs);
  99. printf("imod irefS ifile iref ich szFile\n");
  100. for (IMOD imod = 0; imod < imodMac; imod++) {
  101. for (UINT diref = 0; diref < mpimodcref[imod]; diref++) {
  102. char rgch[256];
  103. UINT iref = mpimodiref[imod] + diref;
  104. ICH ich = mpirefichFile[iref];
  105. ICH cch = (BYTE)rgchNames[ich];
  106. memcpy(rgch, &rgchNames[ich+1], cch);
  107. rgch[cch] = 0;
  108. printf("%4d %5d %5d %4d %5d %s\n",
  109. imod, mpimodiref[imod], diref, iref, ich, rgch);
  110. }
  111. }
  112. delete [] pbAlloc;
  113. putchar('\n');
  114. return TRUE;
  115. }
  116. void dumpMod(Mod* pmod) {
  117. IMOD imod;
  118. char szMod[_MAX_PATH];
  119. CB cbMod = sizeof(szMod);
  120. CB cbSyms, cbLines;
  121. PB pbSyms = 0, pbLines = 0;
  122. if (ModQueryImod(pmod, &imod) &&
  123. ModQueryName(pmod, szMod, &cbMod) &&
  124. ModQuerySymbols(pmod, 0, &cbSyms) &&
  125. (pbSyms = new BYTE[cbSyms]) &&
  126. ModQuerySymbols(pmod, pbSyms, &cbSyms) &&
  127. ModQueryLines(pmod, 0, &cbLines) &&
  128. (pbLines = new BYTE[cbLines]) &&
  129. ModQueryLines(pmod, pbLines, &cbLines))
  130. {
  131. dump(pbSyms, cbSyms, "symbol records for mod %d (%s)", imod, szMod);
  132. dumpSymbols(pbSyms, cbSyms);
  133. dump(pbLines, cbLines, "line numbers for mod %d (%s)", imod, szMod);
  134. dumpLines(pbLines, cbLines);
  135. }
  136. if (pbSyms)
  137. delete [] pbSyms;
  138. if (pbLines)
  139. delete [] pbLines;
  140. }
  141. BOOL dumpGlobals(DBI* pdbi) {
  142. printf("globals:\n");
  143. GSI* pgsi;
  144. return DBIOpenGlobals(pdbi, &pgsi) && dumpGSI(pgsi);
  145. }
  146. BOOL dumpPublics(DBI* pdbi) {
  147. printf("publics:\n");
  148. GSI* pgsi;
  149. return DBIOpenPublics(pdbi, &pgsi) && dumpGSI(pgsi);
  150. }
  151. BOOL dumpGSI(GSI* pgsi) {
  152. PB pbSym = 0;
  153. while (pbSym = GSINextSym(pgsi, pbSym))
  154. dumpSymbol((PSYM)pbSym);
  155. putchar('\n');
  156. return GSIClose(pgsi);
  157. }
  158. inline PB pbEndSym(PSYM psym);
  159. BOOL dumpSymbols(PB pb, CB cb) {
  160. if (cb == 0)
  161. return TRUE;
  162. printf("symbols:\n");
  163. PSYM psymMac = (PSYM)(pb + cb);
  164. for (PSYM psym = (PSYM)(pb + sizeof(ULONG)); psym < psymMac; psym = (PSYM)pbEndSym(psym))
  165. dumpSymbol(psym);
  166. putchar('\n');
  167. return TRUE;
  168. }
  169. typedef SYMTYPE UNALIGNED * PSYMUNALIGNED;
  170. // Return the number of bytes in an ST
  171. inline CB cbForSt(ST st)
  172. {
  173. return *(PB)st + 1;
  174. }
  175. // Return the number of bytes the type record occupies.
  176. inline CB cbForType(PTYPE ptype)
  177. {
  178. return ptype->len + sizeof(ptype->len);
  179. }
  180. // Return a pointer to the byte just past the end of the type record.
  181. inline PB pbEndType(PTYPE ptype)
  182. {
  183. return (PB)ptype + cbForType(ptype);
  184. }
  185. // Return the number of bytes the symbol record occupies.
  186. #define MDALIGNTYPE_ DWORD
  187. inline CB cbAlign_(CB cb)
  188. {
  189. return ((cb + sizeof(MDALIGNTYPE_) - 1)) & ~(sizeof(MDALIGNTYPE_) - 1);
  190. }
  191. inline CB cbForSym(PSYMUNALIGNED psym)
  192. {
  193. CB cb = psym->reclen + sizeof(psym->reclen);
  194. // procrefs also have a hidden length preceeded name following the record
  195. if ((psym->rectyp == S_PROCREF) || (psym->rectyp == S_LPROCREF))
  196. cb += cbAlign_(cbForSt((ST)((PB)psym + cb)));
  197. return cb;
  198. }
  199. // Return a pointer to the byte just past the end of the symbol record.
  200. inline PB pbEndSym(PSYM psym) {
  201. return (PB)psym + cbForSym(psym);
  202. }
  203. inline CString strFmt(SZ szFmt, ...) {
  204. // sigh, there's not CString::VFormat...
  205. va_list va;
  206. va_start(va, szFmt);
  207. char buf[2048];
  208. _vsnprintf(buf, sizeof(buf), szFmt, va);
  209. va_end(va);
  210. buf[sizeof(buf)-1] = 0;
  211. return buf;
  212. }
  213. inline CString strInt(int i) {
  214. return strFmt("%d", i);
  215. }
  216. inline CString strHex(int i) {
  217. return strFmt("%X", i);
  218. }
  219. inline CString strJoin(const CString& s1, const CString& s2) {
  220. if (s1.GetLength() == 0)
  221. return s2;
  222. else if (s2.GetLength() == 0)
  223. return s1;
  224. else if (isalnum(s1.Right(1)[0]) && (isalnum(s2[0]) || !!strchr("?_", s2[0])))
  225. return s1 + " " + s2;
  226. else
  227. return s1 + s2;
  228. }
  229. inline CString strForSt(ST st) {
  230. CString ret;
  231. LPTSTR sz = ret.GetBuffer(cbForSt(st));
  232. memcpy(sz, st+1, cbForSt(st)-1);
  233. sz[cbForSt(st)-1] = 0;
  234. ret.ReleaseBuffer();
  235. return ret;
  236. }
  237. CString strForTypeTi(TI ti, CString str = "", Bind bind = bindNone, BOOL recursed = TRUE);
  238. CString strForDATASYM32(PSYM psym);
  239. CString strForPROCSYM32(PSYM psym);
  240. CString strForREFSYM(PSYM psym);
  241. CString strForUDTSYM(PSYM psym);
  242. CString strForCONSTSYM(PSYM psym);
  243. CString strForLABELSYM32(PSYM psym);
  244. CString strForBPRELSYM32(PSYM psym);
  245. CString strForSymNYI(PSYM psym);
  246. CString strForSymType(unsigned short type);
  247. void dumpSymbol(PSYM psym) {
  248. CString str;
  249. switch (psym->rectyp) {
  250. case S_CONSTANT: str = strForCONSTSYM(psym); break;
  251. case S_UDT: str = strForUDTSYM(psym); break;
  252. case S_BPREL32: str = strForBPRELSYM32(psym); break;
  253. case S_LDATA32: str = strForDATASYM32(psym); break;
  254. case S_GDATA32: str = strForDATASYM32(psym); break;
  255. case S_PUB32: str = strForDATASYM32(psym); break;
  256. case S_LPROC32: str = strForPROCSYM32(psym); break;
  257. case S_GPROC32: str = strForPROCSYM32(psym); break;
  258. case S_LABEL32: str = strForLABELSYM32(psym); break;
  259. case S_PROCREF: /* no point displaying these */ return;
  260. case S_DATAREF: /* no point displaying these */ return;
  261. case S_LPROCREF: /* no point displaying these */ return;
  262. case S_END: str = "end"; break;
  263. default: str = strForSymNYI(psym); break;
  264. }
  265. printf("%-10s: %s;\n", (LPCTSTR)strForSymType(psym->rectyp), (LPCTSTR)str);
  266. }
  267. CString strForSymType(unsigned short type) {
  268. SZ sz = "???";
  269. switch (type) {
  270. #define s(x) case x: sz = #x; break;
  271. s(S_COMPILE)
  272. s(S_REGISTER)
  273. s(S_CONSTANT)
  274. s(S_UDT)
  275. s(S_SSEARCH)
  276. s(S_END)
  277. s(S_SKIP)
  278. s(S_CVRESERVE)
  279. s(S_OBJNAME)
  280. s(S_ENDARG)
  281. s(S_COBOLUDT)
  282. s(S_MANYREG)
  283. s(S_RETURN)
  284. s(S_ENTRYTHIS)
  285. s(S_BPREL16)
  286. s(S_LDATA16)
  287. s(S_GDATA16)
  288. s(S_PUB16)
  289. s(S_LPROC16)
  290. s(S_GPROC16)
  291. s(S_THUNK16)
  292. s(S_BLOCK16)
  293. s(S_WITH16)
  294. s(S_LABEL16)
  295. s(S_CEXMODEL16)
  296. s(S_VFTABLE16)
  297. s(S_REGREL16)
  298. s(S_BPREL32)
  299. s(S_LDATA32)
  300. s(S_GDATA32)
  301. s(S_PUB32)
  302. s(S_LPROC32)
  303. s(S_GPROC32)
  304. s(S_THUNK32)
  305. s(S_BLOCK32)
  306. s(S_WITH32)
  307. s(S_LABEL32)
  308. s(S_CEXMODEL32)
  309. s(S_VFTABLE32)
  310. s(S_REGREL32)
  311. s(S_LTHREAD32)
  312. s(S_GTHREAD32)
  313. s(S_SLINK32)
  314. s(S_LPROCMIPS)
  315. s(S_GPROCMIPS)
  316. s(S_PROCREF)
  317. s(S_DATAREF)
  318. s(S_ALIGN)
  319. s(S_LPROCREF)
  320. }
  321. return sz;
  322. }
  323. CString strForDATASYM32(PSYM psym)
  324. {
  325. DATASYM32* p = (DATASYM32*)psym;
  326. return strForTypeTi(p->typind, strForSt((ST)p->name), bindNone, FALSE);
  327. }
  328. CString strForPROCSYM32(PSYM psym) {
  329. PROCSYM32* p = (PROCSYM32*)psym;
  330. return strForTypeTi(p->typind, strForSt((ST)p->name), bindNone, FALSE);
  331. }
  332. CString strForUDTSYM(PSYM psym) {
  333. UDTSYM* p = (UDTSYM*)psym;
  334. return strForTypeTi(p->typind, strForSt((ST)p->name), bindNone, FALSE);
  335. }
  336. CString strForREFSYM(PSYM psym) {
  337. REFSYM* p = (REFSYM*)psym;
  338. return strFmt("(sumName:%lx ibSym:%lx imod:%d usFill:%x)",
  339. p->sumName, p->ibSym, p->imod, p->usFill);
  340. }
  341. CString strForCONSTSYM(PSYM psym) {
  342. CONSTSYM* p = (CONSTSYM*)psym;
  343. return strForTypeTi(p->typind, strForSt((ST)p->name), bindNone, FALSE);
  344. }
  345. CString strForLABELSYM32(PSYM psym) {
  346. LABELSYM32* p = (LABELSYM32*)psym;
  347. return strForSt((ST)p->name);
  348. }
  349. CString strForBPRELSYM32(PSYM psym) {
  350. BPRELSYM32* p = (BPRELSYM32*)psym;
  351. return strForTypeTi(p->typind, strForSt((ST)p->name), bindNone, FALSE);
  352. }
  353. CString strForSymNYI(PSYM psym) {
  354. return "...";
  355. }
  356. void dumpTpiTi(void* p, int i);
  357. CString strForTI(TI ti);
  358. CString strForPrimitiveTi(TI ti);
  359. CString strForNYI(void* pleaf, CString strBase, Bind bind);
  360. CString strForModifier(lfModifier* pm, CString str);
  361. CString strForPtr(lfPointer* pp, CString strBase, Bind bind);
  362. CString strForArray(lfArray* pa, CString strBase, Bind bind);
  363. CString strForClassStruct(lfStructure* ps, CString strBase, BOOL recursed);
  364. CString strForUnion(lfUnion* pu, CString strBase, BOOL recursed);
  365. CString strForEnum(lfEnum* pe, CString strBase);
  366. CString strForProc(lfProc* pp, CString str, Bind bind);
  367. CString strForMFunc(lfMFunc* pf, CString strBase, Bind bind);
  368. CString strForArgList(lfArgList* pa);
  369. CString strForFieldList(lfFieldList* pf, CB cb);
  370. CString strForMember(lfMember*pdata, CB *pcb);
  371. CString strForBClass(lfBClass* pb, CB* pcb);
  372. CString strForVBClass(lfVBClass* pb, CB* pcb);
  373. CString strForTagTi(TI ti);
  374. CString strForAttr(struct CV_fldattr_t a);
  375. CString strForMember(lfMember* pm, CB *pcb);
  376. CString strForEnumerate(lfEnumerate* pe, CB *pcb);
  377. CString strSep(BOOL& fFirst, char* szFirst = "", char* szRest = ",");
  378. CString strForTI(TI ti) {
  379. return strHex(ti);
  380. }
  381. void dumpType(TI ti) {
  382. printf("%s: %s;\n", (LPCTSTR)strForTI(ti),
  383. (LPCTSTR)strForTypeTi(ti, CString("T") + strForTI(ti), bindNone, FALSE));
  384. }
  385. CString strForTypeTi(TI ti, CString str, Bind bind, BOOL recursed) {
  386. if (ti < TypesQueryTiMin(ptpi)) {
  387. CString strPrim = strForPrimitiveTi(ti);
  388. return strJoin(strPrim, str);
  389. }
  390. PB pb;
  391. if (!TypesQueryPbCVRecordForTi(ptpi, ti, &pb))
  392. return CString("!?!");
  393. TYPTYPE*ptype = (TYPTYPE*)pb;
  394. void* pleaf = &ptype->leaf;
  395. switch (ptype->leaf) {
  396. case LF_MODIFIER: return strForModifier((lfModifier*)pleaf, str);
  397. case LF_POINTER: return strForPtr((lfPointer*)pleaf, str, bind);
  398. case LF_ARRAY: return strForArray((lfArray*)pleaf, str, bind);
  399. case LF_CLASS: return strForClassStruct((lfStructure*)pleaf, str, recursed);
  400. case LF_STRUCTURE: return strForClassStruct((lfStructure*)pleaf, str, recursed);
  401. case LF_UNION: return strForUnion((lfUnion*)pleaf, str, recursed);
  402. case LF_ENUM: return strForEnum((lfEnum*)pleaf, str);
  403. case LF_PROCEDURE: return strForProc((lfProc*)pleaf, str, bind);
  404. case LF_MFUNCTION: return strForMFunc((lfMFunc*)pleaf, str, bind);
  405. case LF_ARGLIST: return strForArgList((lfArgList*)pleaf);
  406. case LF_FIELDLIST: return strForFieldList((lfFieldList*)pleaf, ptype->len);
  407. default:
  408. return strForNYI(pleaf, str, bind);
  409. }
  410. }
  411. CString strForPrimitiveTi(TI ti) {
  412. char* szPrim = 0;
  413. switch (ti) {
  414. #define P(X) case X: szPrim = #X; break;
  415. #define PS(X,S) case X: szPrim = #S; break;
  416. P(T_NOTYPE) P(T_ABS) P(T_SEGMENT) PS(T_VOID,void) PS(T_PVOID,void near*)
  417. PS(T_PFVOID,void far*) PS(T_PHVOID,void huge*) PS(T_32PVOID,void*)
  418. P(T_32PFVOID) P(T_NOTTRANS)
  419. PS(T_CHAR,signed char) PS(T_UCHAR,unsigned char) PS(T_PCHAR,signed char near*)
  420. PS(T_PUCHAR,unsigned char near*) PS(T_PFCHAR,char far*)
  421. PS(T_PFUCHAR,unsigned char far*) PS(T_PHCHAR,char huge*)
  422. PS(T_PHUCHAR,unsigned char huge*) PS(T_32PCHAR,char*)
  423. PS(T_32PUCHAR,unsigned char*) P(T_32PFCHAR) P(T_32PFUCHAR)
  424. PS(T_RCHAR,char) PS(T_PRCHAR,char near*) PS(T_PFRCHAR,char far*)
  425. PS(T_PHRCHAR,char huge*) PS(T_32PRCHAR,char*) P(T_32PFRCHAR)
  426. PS(T_WCHAR,wchar_t) PS(T_PWCHAR,wchar_t near*) PS(T_PFWCHAR,wchar far*)
  427. PS(T_PHWCHAR,wchar_t huge*) PS(T_32PWCHAR,wchar_t*)
  428. P(T_32PFWCHAR) PS(T_SHORT,short) PS(T_USHORT,unsigned)
  429. PS(T_PSHORT,short near*) PS(T_PUSHORT,unsigned short near*)
  430. PS(T_PFSHORT,short far*) PS(T_PFUSHORT,unsigned short far*)
  431. PS(T_PHSHORT,short huge*) PS(T_PHUSHORT,unsigned short huge*)
  432. P(T_32PSHORT) P(T_32PUSHORT) P(T_32PFSHORT)
  433. P(T_32PFUSHORT) PS(T_INT2,int16) PS(T_UINT2,unsigned int16)
  434. PS(T_PINT2,int16 near*) PS(T_PUINT2,unsigned int16 near*)
  435. PS(T_PFINT2,int16 far*) PS(T_PFUINT2,unsigned int16 far*)
  436. PS(T_PHINT2,int16 huge*) PS(T_PHUINT2,unsigned int16 huge*) P(T_32PINT2)
  437. P(T_32PUINT2) P(T_32PFINT2) P(T_32PFUINT2) PS(T_LONG,long)
  438. PS(T_ULONG,unsigned long) PS(T_PLONG,long near*)
  439. PS(T_PULONG,unsigned long near*) PS(T_PFLONG,long far*)
  440. PS(T_PFULONG,unsigned long far*) PS(T_PHLONG,long huge*)
  441. PS(T_PHULONG,unsigned long huge*) PS(T_32PLONG, long*)
  442. PS(T_32PULONG, unsigned long*) P(T_32PFLONG)
  443. P(T_32PFULONG) PS(T_INT4,int) PS(T_UINT4,unsigned)
  444. P(T_PINT4) P(T_PUINT4) P(T_PFINT4) P(T_PFUINT4) P(T_PHINT4) P(T_PHUINT4)
  445. PS(T_32PINT4,int *) PS(T_32PUINT4,unsigned*)
  446. P(T_32PFINT4) P(T_32PFUINT4)
  447. //
  448. // The following were added for BIGINT support
  449. //
  450. PS(T_QUAD,quad) PS(T_UQUAD,unsigned quad) PS(T_PQUAD,quad near*)
  451. PS(T_PUQUAD,unsigned quad near*) PS(T_PFQUAD,quad far*)
  452. PS(T_PFUQUAD,unsigned quad far*) PS(T_PHQUAD,quad huge*)
  453. PS(T_PHUQUAD,unsigned quad huge*) P(T_32PQUAD) P(T_32PUQUAD) P(T_32PFQUAD)
  454. P(T_32PFUQUAD)
  455. PS(T_INT8,int64) PS(T_UINT8,unsigned int64) PS(T_PINT8,int64 near*)
  456. PS(T_PUINT8,unsigned int64 near*) PS(T_PFINT8,int64 far*)
  457. PS(T_PFUINT8,unsigned int64 far*) PS(T_PHINT8,int64 huge*)
  458. PS(T_PHUINT8,unsigned int64 huge*) P(T_32PINT8) P(T_32PUINT8) P(T_32PFINT8)
  459. P(T_32PFUINT8)
  460. PS(T_REAL32,float) PS(T_PREAL32,float near*)
  461. PS(T_PFREAL32,float far*) PS(T_PHREAL32,float huge*)
  462. PS(T_32PREAL32,float*) P(T_32PFREAL32) PS(T_REAL64,double)
  463. PS(T_PREAL64,double near*) PS(T_PFREAL64,double far*)
  464. PS(T_PHREAL64,double huge*) PS(T_32PREAL64,double*)
  465. P(T_32PFREAL64) PS(T_REAL80,long double) PS(T_PREAL80,long double near*)
  466. PS(T_PFREAL80,long double far*) PS(T_PHREAL80,long double huge*)
  467. PS(T_32PREAL80,long double*) P(T_32PFREAL80)
  468. }
  469. return szPrim ? CString(szPrim) : CString("<") + strForTI(ti) + ">";
  470. }
  471. CString strForNYI(void* pleaf, CString strBase, Bind bind) {
  472. return "<<" + strBase + ">>";
  473. }
  474. CString strForModifier(lfModifier* pm, CString str) {
  475. CString strMod;
  476. if (pm->attr.MOD_const)
  477. strMod += "const ";
  478. if (pm->attr.MOD_volatile)
  479. strMod += "volatile ";
  480. return strMod + strForTypeTi(pm->type) + str;
  481. }
  482. CString strForPtr(lfPointer* pp, CString strBase, Bind bind) {
  483. static char* mppmenumsz[] = {
  484. "pdm16_nonvirt", "pdm16_vfcn", "pdm16_vbase", "pdm32_nvvfcn",
  485. "pdm32_vbase", "pmf16_nearnvsa", "pmf16_nearnvma", "pmf16_nearvbase",
  486. "pmf16_farnvsa", "pmf16_farnvma", "pmf16_farvbase", "pmf32_nvsa",
  487. "pmf32_nvma", "pmf32_vbase"
  488. };
  489. static char* mpptrtypesz[] = {
  490. "near", "far", "huge", "base(seg)",
  491. "base(val)", "base(segval)", "base(addr)", "base(segaddr)",
  492. "base(type)", "base(self)", "", "far32"
  493. };
  494. CString str;
  495. if (pp->attr.isflat32)
  496. str = "flat ";
  497. switch (pp->attr.ptrmode) {
  498. case CV_PTR_MODE_PTR:
  499. str += CString(mpptrtypesz[pp->attr.ptrtype]) + "*";
  500. break;
  501. case CV_PTR_MODE_REF:
  502. str += CString(mpptrtypesz[pp->attr.ptrtype]) + "&";
  503. break;
  504. case CV_PTR_MODE_PMEM:
  505. case CV_PTR_MODE_PMFUNC:
  506. str = strForTypeTi(pp->pbase.pm.pmclass) + "::*";
  507. break;
  508. }
  509. if (pp->attr.isconst)
  510. str += "const";
  511. if (pp->attr.isvolatile)
  512. str += "volatile";
  513. // TODO: exotic based modes
  514. return strForTypeTi(pp->utype, strJoin(str, strBase), bindPtr);
  515. }
  516. CB CbExtractNumeric(BYTE* pb, ULONG* pul);
  517. CString strForArray(lfArray* pa, CString strBase, Bind bind) {
  518. if (bind < bindArray)
  519. strBase = "(" + strBase + ")";
  520. ULONG size;
  521. CbExtractNumeric(pa->data, &size);
  522. CString str = strBase + "[" + strInt(size) + "]";
  523. // TODO: exotic subscript types
  524. return strForTypeTi(pa->elemtype, str, bindArray);
  525. }
  526. CString strForClassStruct(lfStructure* ps, CString strBase, BOOL recursed) {
  527. ULONG size;
  528. CB dcb = CbExtractNumeric(ps->data, &size);
  529. CString str;
  530. if (!recursed)
  531. str += (ps->leaf == LF_STRUCTURE) ? "struct " : "class ";
  532. str += strForSt((char*)ps->data + dcb);
  533. if (ps->field)
  534. str += strForTypeTi(ps->field);
  535. return strJoin(str, strBase);
  536. }
  537. CString strForUnion(lfUnion* pu, CString strBase, BOOL recursed) {
  538. ULONG size;
  539. CB dcb = CbExtractNumeric(pu->data, &size);
  540. CString str;
  541. if (!recursed)
  542. str += "union ";
  543. str += strForSt((char*)pu->data + dcb);
  544. if (pu->field)
  545. str += strForTypeTi(pu->field);
  546. return strJoin(str, strBase);
  547. }
  548. CString strForEnum(lfEnum* pe, CString strBase) {
  549. CString str = "enum ";
  550. str += strForSt((char*)pe->Name);
  551. if (pe->field)
  552. str += strForTypeTi(pe->field);
  553. return strJoin(str, strBase);
  554. }
  555. CString strForFieldList(lfFieldList* pfl, CB cbList) {
  556. CString str;
  557. PB pdata;
  558. CB cb = 0;
  559. BOOL fBases = TRUE;
  560. BOOL fMembers = TRUE;
  561. while (cb < cbList) {
  562. // skip pad bytes
  563. for (;;) {
  564. pdata = (PB)pfl->data + cb;
  565. if (*(BYTE*)pdata < LF_PAD0)
  566. break;
  567. cb++;
  568. }
  569. switch (*(USHORT*)pdata) {
  570. case LF_BCLASS:
  571. str += strSep(fBases, " : ", ", ");
  572. str += strForBClass((lfBClass*)pdata, &cb);
  573. break;
  574. case LF_VBCLASS:
  575. case LF_IVBCLASS:
  576. str += strSep(fBases, " : ", ", ");
  577. str += strForVBClass((lfVBClass*)pdata, &cb);
  578. break;
  579. case LF_MEMBER:
  580. str += strSep(fMembers, " { ", " ");
  581. str += strForMember((lfMember*)pdata, &cb);
  582. str += ";";
  583. break;
  584. case LF_ENUMERATE:
  585. str += strSep(fMembers, " { ", " ");
  586. str += strForEnumerate((lfEnumerate*)pdata, &cb);
  587. str += ",";
  588. default:
  589. str += "...";
  590. goto out;
  591. }
  592. }
  593. out:
  594. str += strSep(fMembers, " {}", " }");
  595. return str;
  596. }
  597. CString strForBClass(lfBClass* pb, CB* pcb) {
  598. ULONG offset;
  599. *pcb += sizeof(lfBClass) + CbExtractNumeric(pb->offset, &offset);
  600. return strJoin(strForAttr(pb->attr), strForTypeTi(pb->index));
  601. }
  602. CString strForVBClass(lfVBClass* pb, CB* pcb) {
  603. BOOL fInd = (pb->leaf == LF_IVBCLASS);
  604. CString str;
  605. ULONG offVbp;
  606. ULONG offVbte;
  607. CB cb = CbExtractNumeric(pb->vbpoff, &offVbp);
  608. *pcb += sizeof(lfVBClass) + cb +
  609. CbExtractNumeric(pb->vbpoff + cb, &offVbte);
  610. if (fInd)
  611. str = "< indirect ";
  612. str += strJoin(strForAttr(pb->attr), strForTagTi(pb->index));
  613. if (!fInd)
  614. str += "< ";
  615. str += strForTypeTi(pb->vbptr, "vbp") + ";";
  616. str += CString("offVbp=") + strInt(offVbp) + "; offVbte=" + strInt(offVbte) + ";";
  617. str += " >";
  618. return str;
  619. }
  620. CString strForTagTi(TI ti) {
  621. PB pb;
  622. if (!TypesQueryPbCVRecordForTi(ptpi, ti, &pb))
  623. return CString("!?!");
  624. TYPTYPE* ptype = (TYPTYPE*)pb;
  625. if (!(ptype->leaf == LF_STRUCTURE || ptype->leaf == LF_CLASS))
  626. return CString("!?!");
  627. lfStructure* ps = (lfStructure*)&ptype->leaf;
  628. ULONG size;
  629. CB dcb = CbExtractNumeric(ps->data, &size);
  630. return strForSt((char*)ps->data + dcb);
  631. }
  632. CString strForMember(lfMember* pm, CB *pcb) {
  633. ULONG offset;
  634. CB cbOffset = CbExtractNumeric(pm->offset, &offset);
  635. CString str = /* strForAttr(pm->attr) + ": " + */
  636. strForTypeTi(pm->index, strForSt((char*)pm->offset + cbOffset));
  637. *pcb += sizeof(lfMember) + cbOffset + pm->offset[cbOffset] + 1;
  638. return str;
  639. }
  640. CString strForAttr(struct CV_fldattr_t a) {
  641. static char* mpaccesssz[] = { "", "private", "protected", "public" };
  642. static char* mpmpropsz[] = { "", "virtual", "static", "friend",
  643. "", "<pure>", "<pure>" };
  644. CString str = CString(mpaccesssz[a.access]) + CString(mpmpropsz[a.mprop]);
  645. return str;
  646. }
  647. CString strForProc(lfProc* pp, CString strBase, Bind bind) {
  648. if (bind < bindProc)
  649. strBase = "(" + strBase + ")";
  650. strBase += strForTypeTi(pp->arglist);
  651. return strForTypeTi(pp->rvtype, CString(" ") + strBase, bindProc);
  652. }
  653. CString strForMFunc(lfMFunc* pf, CString strBase, Bind bind) {
  654. if (bind < bindProc)
  655. strBase = "(" + strBase + ")";
  656. CString str;
  657. str = CString(" ") + strForTypeTi(pf->classtype) + "::";
  658. str += strBase + strForTypeTi(pf->arglist);
  659. str += CString("<") + strForTypeTi(pf->thistype, "this") + ">";
  660. return strForTypeTi(pf->rvtype, str, bindProc);
  661. }
  662. CString strForArgList(lfArgList* pa) {
  663. CString str = "(";
  664. for (int i = 0; i < pa->count; i++) {
  665. if (i > 0)
  666. str += ", ";
  667. str += strForTypeTi(pa->arg[i]);
  668. }
  669. str += ")";
  670. return str;
  671. }
  672. CString strForEnumerate(lfEnumerate* pe, CB *pcb) {
  673. ULONG value;
  674. CB cb = CbExtractNumeric(pe->value, &value);
  675. return strForSt((char*)pe->value + cb) + "=" + strInt(value);
  676. *pcb += sizeof(lfEnumerate) + cb + pe->value[cb] + 1;
  677. }
  678. CString strSep(BOOL& fFirst, char* szFirst, char* szRest) {
  679. CString str = fFirst ? szFirst : szRest;
  680. fFirst = FALSE;
  681. return str;
  682. }
  683. CB CbExtractNumeric(BYTE* pb, ULONG* pul) {
  684. USHORT leaf = *(USHORT*)pb;
  685. if (leaf < LF_NUMERIC) {
  686. *pul = leaf;
  687. return sizeof(leaf);
  688. } else switch (leaf) {
  689. case LF_CHAR:
  690. *pul = *((char*)pb);
  691. return sizeof(leaf) + sizeof(char);
  692. case LF_SHORT:
  693. *pul = *(short*)pb;
  694. return sizeof(leaf) + sizeof(short);
  695. case LF_USHORT:
  696. *pul = *(USHORT*)pb;
  697. return sizeof(leaf) + sizeof(USHORT);
  698. case LF_LONG:
  699. *pul = *(long*)pb;
  700. return sizeof(leaf) + sizeof(long);
  701. case LF_ULONG:
  702. *pul = *(ULONG*)pb;
  703. return sizeof(leaf) + sizeof(ULONG);
  704. }
  705. return 0;
  706. }
  707. BOOL dumpLines(PB pb, CB cb) {
  708. if (cb == 0)
  709. return TRUE;
  710. PB pbLines = pb;
  711. struct FSB { short cFile; short cSeg; long baseSrcFile[]; };
  712. FSB* pfsb = (FSB*)pb;
  713. pb += sizeof(FSB) + sizeof(long)*pfsb->cFile;
  714. struct SE { long start, end; };
  715. SE* pse = (SE*)pb;
  716. pb += sizeof(SE)*pfsb->cSeg;
  717. short* seg = (short*)pb;
  718. pb += sizeof(short)*pfsb->cSeg;
  719. printf("lines: cFile=%u cSeg=%u\n", pfsb->cFile, pfsb->cSeg);
  720. for (int ifile = 0; ifile < pfsb->cFile; ifile++)
  721. printf("baseSrcFile[%d]=%04lx\n", ifile, pfsb->baseSrcFile[ifile]);
  722. for (int iseg = 0; iseg < pfsb->cSeg; iseg++)
  723. printf("%d: start=%04lx end=%04lx seg=%02x\n",
  724. iseg, pse[iseg].start, pse[iseg].end, seg[iseg]);
  725. for (ifile = 0; ifile < pfsb->cFile; ifile++) {
  726. PB pb = pbLines + pfsb->baseSrcFile[ifile];
  727. struct SPB { short cSeg; short pad; long baseSrcLn[]; };
  728. SPB* pspb = (SPB*)pb;
  729. pb += sizeof SPB + sizeof(long)*pspb->cSeg;
  730. SE* pse = (SE*)pb;
  731. pb += sizeof(SE)*pspb->cSeg;
  732. unsigned char cbName = *pb++;
  733. unsigned char* Name = pb;
  734. printf(" file[%d]: cSeg=%u pad=%02x cbName=%u, Name=%s\n",
  735. ifile, pspb->cSeg, pspb->pad, cbName, Name);
  736. for (int iseg = 0; iseg < pspb->cSeg; iseg++)
  737. printf(" %d: baseSrcLn=%04lx start=%04lx end=%04lx\n",
  738. iseg, pspb->baseSrcLn[iseg], pse[iseg].start, pse[iseg].end);
  739. for (iseg = 0; iseg < pspb->cSeg; iseg++) {
  740. PB pb = pbLines + pspb->baseSrcLn[iseg];
  741. struct SPO { short Seg; short cPair; long offset[]; };
  742. SPO* pspo = (SPO*)pb;
  743. pb += sizeof(SPO) + sizeof(long)*pspo->cPair;
  744. short* linenumber = (short*)pb;
  745. printf(" seg[%d]: Seg=%02x cPair=%u\n", iseg, pspo->Seg, pspo->cPair);
  746. printf(" ");
  747. for (int ipair = 0; ipair < pspo->cPair; ipair++) {
  748. printf(" %4u:%04lx", linenumber[ipair], pspo->offset[ipair]);
  749. if (ipair < pspo->cPair - 1 && (ipair & 3) == 3)
  750. printf("\n ");
  751. }
  752. putchar('\n');
  753. }
  754. }
  755. putchar('\n');
  756. return TRUE;
  757. }
  758. void dump(PB pb, CB cb, SZ szFmt, ...) {
  759. va_list va;
  760. printf("raw hex dump of ");
  761. va_start(va, szFmt);
  762. vprintf(szFmt, va);
  763. va_end(va);
  764. if (cb > 0)
  765. printf(":\n");
  766. else {
  767. printf(": (none)\n\n");
  768. return;
  769. }
  770. PB pbStart = pb;
  771. PB pbEnd = pbStart + cb;
  772. const int n = 16;
  773. for ( ; pb < pbEnd; pb += n) {
  774. printf("%06X: ", pb - pbStart);
  775. for (int i = 0; i < n; i++) {
  776. if (i == n/2)
  777. putchar(' ');
  778. if (&pb[i] < pbEnd)
  779. printf("%02X ", pb[i]);
  780. else
  781. printf(" ");
  782. }
  783. putchar(' ');
  784. for (i = 0; i < n && &pb[i] < pbEnd; i++)
  785. putchar(isprint(pb[i]) ? pb[i] : '.');
  786. putchar('\n');
  787. }
  788. putchar('\n');
  789. }