Leaked source code of windows server 2003
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.

757 lines
19 KiB

  1. /* Chris Peters
  2. * CHANGED: Fritz Knabe, 7/28/87
  3. * mikedr, 8/8/88 - read offset bytes after 0xff seg no on swap
  4. * allow specification of data file location
  5. * c-chrisc [Christine Comaford], 10/31/89 - added "-i" flag to
  6. * allow symbol file path spec on command line, added "-m"
  7. * flag to precede module spec, rewrote module parser,
  8. * added usage display, misc other enhancements.
  9. *
  10. * Copyright Microsoft Corporation, 1985-1990
  11. */
  12. #include <string.h>
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <assert.h>
  16. #include <memory.h>
  17. #include <malloc.h>
  18. #include <stdlib.h>
  19. /* standard stuff */
  20. typedef unsigned char BYTE;
  21. typedef unsigned short WORD;
  22. typedef unsigned long DWORD;
  23. typedef int BOOL;
  24. #define TRUE 1
  25. #define FALSE 0
  26. BOOL FModuleMatch(BYTE *, BYTE);
  27. int GetSymbolString(BYTE *, BYTE *, WORD, WORD);
  28. int GetSegNum(char *, char *);
  29. BYTE *htoa(BYTE *, WORD);
  30. char *ProcessArguments(int, char **);
  31. /* Debug Symbol Table Structures
  32. -----------------------------
  33. For each symbol table (map): (MAPDEF)
  34. -------------------------------------------------------------------------------------------------
  35. | map_ptr | lsa | pgm_ent | abs_cnt | abs_ptr | seg_cnt | seg_ptr | nam_max | nam_len | name... |
  36. ------------------------------------------------------------------------------------------------- */
  37. struct mapdef
  38. {
  39. unsigned map_ptr; /* 16 bit ptr to next map (0 if end) */
  40. unsigned lsa ; /* 16 bit Load Segment address */
  41. unsigned pgm_ent; /* 16 bit entry point segment value */
  42. int abs_cnt; /* 16 bit count of constants in map */
  43. unsigned abs_ptr; /* 16 bit ptr to constant chain */
  44. int seg_cnt; /* 16 bit count of segments in map */
  45. unsigned seg_ptr; /* 16 bit ptr to segment chain */
  46. char nam_max; /* 8 bit Maximum Symbol name length */
  47. char nam_len; /* 8 bit Symbol table name length */
  48. };
  49. struct mapend
  50. {
  51. unsigned chnend; /* end of map chain (0) */
  52. char rel; /* release */
  53. char ver; /* version */
  54. };
  55. /* For each segment/group within a symbol table: (SEGDEF)
  56. --------------------------------------------------------------
  57. | nxt_seg | sym_cnt | sym_ptr | seg_lsa | name_len | name... |
  58. -------------------------------------------------------------- */
  59. struct segdef
  60. {
  61. unsigned nxt_seg; /* 16 bit ptr to next segment(0 if end) */
  62. int sym_cnt; /* 16 bit count of symbols in sym list */
  63. unsigned sym_ptr; /* 16 bit ptr to symbol list */
  64. unsigned seg_lsa; /* 16 bit Load Segment address */
  65. unsigned seg_in0; /* 16 bit instance 0 physical address */
  66. unsigned seg_in1; /* 16 bit instance 1 physical address */
  67. unsigned seg_in2; /* 16 bit instance 2 physical address */
  68. unsigned seg_in3; /* 16 bit instance 3 physical address */
  69. unsigned seg_lin; /* 16 bit ptr to line number record */
  70. char seg_ldd; /* 8 bit boolean 0 if seg not loaded */
  71. char seg_cin; /* 8 bit current instance */
  72. char nam_len; /* 8 bit Segment name length */
  73. };
  74. /* Followed by a list of SYMDEF's..
  75. for each symbol within a segment/group: (SYMDEF)
  76. -------------------------------
  77. | sym_val | nam_len | name... |
  78. ------------------------------- */
  79. struct symdef
  80. {
  81. unsigned sym_val; /* 16 bit symbol addr or const */
  82. char nam_len; /* 8 bit symbol name length */
  83. };
  84. typedef struct tagMODSEG /* Structure for saving information */
  85. { /* about cmd line arguments */
  86. int segno; /* Special values:
  87. -1 information about all segments in the module
  88. is supplied
  89. -2 an invalid segment name was supplied, i.e.
  90. nothing matches this record/argument
  91. >=0 valid segment number
  92. */
  93. char szModule[32]; /* Name of module */
  94. } MODSEG, *PMODSEG;
  95. /*----------------------------------------------------------------------------
  96. | Global Variables
  97. |
  98. ----------------------------------------------------------------------------*/
  99. #define MAX_ARGS 34 /* arbitrary (but reasonable) values */
  100. #define MAX_PATHS 16
  101. char curpath_buffer[65]; /* buffer holding current sym file path */
  102. char path_buffer[132]; /* buffer holding cmd line sym path string */
  103. char *path_table[MAX_PATHS]; /* table of sym file buffers */
  104. int num_paths = 0; /* index into path_table[] */
  105. int nNumArgs; /* Number of command line arguments */
  106. char *ModSegTab[MAX_ARGS]; /* Table of MODSEG records */
  107. BOOL bModule = FALSE; /* is module specified on command line? */
  108. BOOL bSymPath = FALSE; /* is symbol file path specified on command line? */
  109. int num_mods = 0; /* index into module table */
  110. char usage[] = "\nUSAGE: SWAP [-Ipath1;path2;...] [-Fswapfile] [-Mmod1[:seg];mod2[:seg];...]\n\n"
  111. " -Ipath1;path2;... -- Path list for .SYM files.\n\n"
  112. " -Fswapfile -- Name and path of swap file,\n"
  113. " default: swappro.dat.\n\n"
  114. " -Mmod1[:seg];mod2[:seg];... -- Name of module or module:segment\n"
  115. " pairs to return swap data for.\n";
  116. /*----------------------------------------------------------------------------
  117. | Main Program
  118. |
  119. |
  120. ----------------------------------------------------------------------------*/
  121. /* Structure of swappro.dat records:
  122. BYTE type; 0 = Call, 1 = Swap, 2 = Discard, 3 = Return
  123. WORD time;
  124. BYTE nam_len; Length of following name (not null terminated)
  125. BYTE name[];
  126. BYTE segno; This is the end of the record for DISCARD records
  127. or resources (segno == 0xFF)
  128. WORD offset; This is the end of the record for types 2 and 3
  129. BYTE nam2_len; If 0, the next field missing, and the name is the
  130. same as the previous one
  131. BYTE name2[];
  132. BYTE segno2;
  133. BYTE offset2;
  134. */
  135. main(argc, argv)
  136. int argc;
  137. char *argv[];
  138. {
  139. register FILE *pfIn;
  140. BYTE rgch1[256];
  141. BYTE rgch2[256];
  142. register BYTE stModule[32], stModule2[32];
  143. BYTE rt;
  144. BYTE cch;
  145. WORD t;
  146. WORD segno = 0, segno2 = 0;
  147. WORD offset, offset2;
  148. BOOL fFirst = TRUE;
  149. long time, timePrev, timeBase;
  150. char *filepath;
  151. /* sign on */
  152. printf("Microsoft (R) Swap File Analyzer Version 3.00\n");
  153. printf("Copyright (C) Microsoft Corp 1990. All rights reserved.\n\n");
  154. filepath = ProcessArguments(argc, argv);
  155. if (filepath == NULL)
  156. filepath = "swappro.dat";
  157. pfIn = fopen(filepath,"rb");
  158. if (pfIn == NULL)
  159. {
  160. printf("\nFile %s not found.\n",filepath);
  161. exit(2);
  162. }
  163. printf("\nType\tTime\tSegment\tOffset\tSegment\tOffset");
  164. printf("\n----\t----\t-------\t------\t-------\t------");
  165. while(!feof(pfIn))
  166. {
  167. fread(&rt, 1, 1, pfIn); /* Get the record type */
  168. timePrev = time;
  169. fread(&t, 2, 1, pfIn); /* Get the time */
  170. time = t;
  171. if (fFirst)
  172. {
  173. timePrev = 0;
  174. timeBase = time;
  175. fFirst = FALSE;
  176. }
  177. time -= timeBase;
  178. if (time < timePrev)
  179. {
  180. time += 65536;
  181. timeBase -= 65536;
  182. }
  183. switch (rt)
  184. {
  185. default:
  186. printf("\n **** Invalid swap record ****");
  187. break;
  188. case 0: /* Call */
  189. case 1: /* Swap */
  190. fread(stModule, 1, 1, pfIn);
  191. fread(stModule+1, 1, stModule[0], pfIn);
  192. fread(&segno, 1, 1, pfIn);
  193. if (segno != 0xFF)
  194. fread(&offset, 2, 1, pfIn);
  195. else /* We have a RESOURCE, so we don't fread */
  196. offset = 0xFFFF;
  197. fread(stModule2, 1, 1, pfIn);
  198. /* Check if this module name is the same as
  199. stModule */
  200. if (stModule2[0])
  201. fread(stModule2+1, 1, stModule2[0], pfIn);
  202. else
  203. memcpy(stModule2, stModule, 1 + stModule[0]);
  204. /* read segment and offset */
  205. fread(&segno2, 1, 1, pfIn);
  206. fread(&offset2, 2, 1, pfIn);
  207. if (segno2 == 0xFF)
  208. offset2 = 0xFFFF;
  209. if (bModule)
  210. {
  211. if (!FModuleMatch(stModule, segno) &&
  212. !FModuleMatch(stModule2, segno2))
  213. break;
  214. }
  215. GetSymbolString(rgch1, stModule, segno, offset);
  216. GetSymbolString(rgch2, stModule2, segno2, offset2);
  217. if (rt == 1)
  218. printf("\nSwap");
  219. else
  220. printf("\nCall");
  221. printf("\t%ld\t%s\t%s",time, rgch1, rgch2);
  222. break;
  223. case 2: /* Discard */
  224. case 3: /* Return */
  225. fread(stModule, 1, 1, pfIn);
  226. fread(stModule+1, 1, stModule[0], pfIn);
  227. fread(&segno, 1, 1, pfIn);
  228. if (rt == 2 || segno == 0xFF)
  229. offset = 0xFFFF;
  230. else
  231. /* Only read offset if not a DISCARD
  232. record or a resource */
  233. fread(&offset, 2, 1, pfIn);
  234. if (bModule)
  235. {
  236. if (!FModuleMatch(stModule, segno))
  237. break;
  238. }
  239. GetSymbolString(rgch1, stModule, segno, offset);
  240. if (rt == 2)
  241. printf("\nDiscard");
  242. else
  243. printf("\nReturn");
  244. printf("\t%ld\t%s",time,rgch1);
  245. break;
  246. }
  247. }
  248. }
  249. /* returns pointer to swap data file name, NULL if none given */
  250. char *ProcessArguments(argc, argv)
  251. int argc;
  252. char *argv[];
  253. {
  254. PMODSEG pms;
  255. int i,j;
  256. int nArgSep = 0;
  257. int n = 0;
  258. char *filepath = NULL;
  259. char *curpath;
  260. char ch;
  261. char *opt;
  262. char module_buffer[132];
  263. char *curmodule;
  264. #define MAX_MODULES 20
  265. char *module_table[MAX_MODULES];
  266. nNumArgs = (int) min(argc,MAX_ARGS);
  267. if (nNumArgs < 2) /* No arguments */
  268. return(filepath);
  269. for (i = 1; i < argc; i++)
  270. {
  271. if ((*argv[i] == '-' || *argv[i] == '/'))
  272. {
  273. ch = tolower(argv[i][1]);
  274. switch (ch) {
  275. case 'f':
  276. /* create swap data file spec */
  277. filepath = &argv[i][2]; /* first char past flag */
  278. if (!*filepath) /* skip white space */
  279. {
  280. i++; /* adjust command line variables */
  281. nNumArgs--;
  282. filepath = argv[i]; /* get file name from next arg */
  283. }
  284. nNumArgs--;
  285. break;
  286. case 'i':
  287. bSymPath = TRUE;
  288. /* place the current directory at the head of the symbol
  289. table path */
  290. getcwd(curpath_buffer, 132);
  291. path_table[num_paths++] = curpath_buffer;
  292. /* create symbol file spec */
  293. strcpy(path_buffer, &argv[i][2]);
  294. if (!*path_buffer)
  295. {
  296. /* space after flag, so increment index */
  297. i++;
  298. /* adjust command line arg count */
  299. nNumArgs--;
  300. /* get all symbol file path names from next arg */
  301. strcpy (path_buffer, argv[i]);
  302. }
  303. strcat(path_buffer, ";");
  304. curpath = strtok(path_buffer, ";");
  305. do {
  306. path_table[num_paths++] = curpath;
  307. } while (curpath = strtok(NULL, ";"));
  308. break;
  309. case 'm':
  310. /* create module and/or module:_segment file spec */
  311. bModule = TRUE;
  312. strcpy(module_buffer, &argv[i][2]);
  313. if (!*module_buffer)
  314. {
  315. i++;
  316. nNumArgs--;
  317. strcpy(module_buffer, argv[i]);
  318. }
  319. strcat(module_buffer, ";");
  320. /* fill module table with mod names */
  321. curmodule = strtok(module_buffer, ";");
  322. do {
  323. module_table[num_mods++] = curmodule;
  324. } while (curmodule = strtok(NULL, ";"));
  325. /* for each module, assign segno if applicable */
  326. for (j = 0; j < num_mods; j++)
  327. {
  328. if (!(pms = (PMODSEG) malloc(sizeof(MODSEG))))
  329. {
  330. printf ("MEMORY ALLOCATION FAILED!!!!");
  331. exit (1);
  332. }
  333. /* determine whether a segment has been specified
  334. (i.e., GDI:_FONTRES), look for a ':' */
  335. nArgSep = strcspn(module_table[j], ":");
  336. strncpy(pms->szModule, module_table[j], nArgSep);
  337. pms->szModule[nArgSep] = '\0';
  338. /* Get segment number */
  339. /* First case: no segment specified; e.g. format of
  340. arg would be "user" */
  341. if (nArgSep == strlen(module_table[j]) ||
  342. module_table[j][nArgSep+1] == '\0')
  343. pms->segno = -1;
  344. /* Second case: decimal segment number supplied; e.g.
  345. "user:10" */
  346. else if (isdigit(module_table[j][nArgSep+1]))
  347. pms->segno = atoi(module_table[j]+nArgSep+1);
  348. /* Third case: the segment name is "resource" */
  349. else if (strcmpi(module_table[j]+nArgSep+1, "RESOURCE") == 0)
  350. pms->segno = 0xFF;
  351. /* Fourth case: a segment name is supplied; get
  352. it's number */
  353. else
  354. {
  355. pms->segno = GetSegNum(pms->szModule,
  356. module_table[j]+nArgSep+1);
  357. }
  358. ModSegTab[n++] = (char *) pms;
  359. }
  360. break;
  361. default:
  362. /* Display cmd line args and quit */
  363. fprintf(stderr, usage);
  364. exit(1);
  365. }
  366. }
  367. }
  368. return(filepath);
  369. }
  370. /* Determines whether module specified on command line is equal to
  371. current module read in. No called if no mod, mod/seg is specified on
  372. command line. If false is returned, record won't be displayed. */
  373. BOOL FModuleMatch(stModule, segno)
  374. register BYTE stModule[];
  375. BYTE segno;
  376. {
  377. register int i;
  378. PMODSEG pms;
  379. if (nNumArgs < 2)
  380. return TRUE;
  381. stModule[stModule[0]+1] = '\0';
  382. for (i = 0; i < num_mods; i++)
  383. {
  384. pms = (PMODSEG) ModSegTab[i];
  385. if (strcmpi(stModule+1, pms->szModule) == 0 &&
  386. (pms->segno == -1 || pms->segno == segno))
  387. return(TRUE);
  388. }
  389. return(FALSE);
  390. }
  391. int GetSegNum(szModule, szSegment)
  392. char *szModule;
  393. char *szSegment;
  394. {
  395. /* Gets the number of the named segment in the named module, if it exists.
  396. This is a "stripped" version of GetSymbolString. */
  397. char buf[50];
  398. FILE *pfSym;
  399. struct mapdef MAPDEF;
  400. struct mapend MAPEND;
  401. struct segdef SEGDEF;
  402. WORD seg_ptr, fstseg_ptr;
  403. int i;
  404. register int pathcnt;
  405. char symfile[65];
  406. strcpy(symfile, szModule);
  407. strcat(symfile, ".SYM");
  408. if (bSymPath)
  409. {
  410. /* Loop through all symbol file paths until file is found */
  411. for (pathcnt=0; pathcnt <num_paths; pathcnt++)
  412. {
  413. strcpy(buf, path_table[pathcnt]);
  414. strcat(buf, "\\");
  415. strcat(buf, symfile);
  416. if (pfSym = fopen(buf, "rb"))
  417. break;
  418. }
  419. }
  420. else
  421. pfSym = fopen(symfile, "rb");
  422. if (!pfSym)
  423. return -1;
  424. fread(&MAPDEF, 1, sizeof(MAPDEF), pfSym);
  425. fstseg_ptr = seg_ptr = (WORD)MAPDEF.seg_ptr;
  426. fseek(pfSym, (long)-sizeof(MAPEND), 2);
  427. fread(&MAPEND, 1, sizeof(MAPEND), pfSym);
  428. if (MAPEND.ver != 3)
  429. {
  430. fclose(pfSym);
  431. return -1;
  432. }
  433. i = 0;
  434. do
  435. {
  436. if (MAPEND.rel >= 10)
  437. fseek(pfSym, (long)(seg_ptr * 16), 0);
  438. else
  439. fseek(pfSym, (long)seg_ptr, 0);
  440. fread(&SEGDEF, 1, sizeof(SEGDEF), pfSym);
  441. seg_ptr = (WORD)SEGDEF.nxt_seg;
  442. fread(buf, 1, SEGDEF.nam_len, pfSym);
  443. buf[SEGDEF.nam_len] = '\0';
  444. if (strcmpi(buf, szSegment) == 0)
  445. {
  446. fclose(pfSym);
  447. return i;
  448. }
  449. i++;
  450. }
  451. while (seg_ptr && seg_ptr != fstseg_ptr);
  452. fclose(pfSym);
  453. return -2;
  454. }
  455. int GetSymbolString(pchOut, stModule, segno, offset)
  456. BYTE *pchOut; /* output buffer */
  457. BYTE stModule[]; /* module name */
  458. WORD segno; /* segment number */
  459. WORD offset; /* offset into segment */
  460. {
  461. int cch;
  462. register int i;
  463. register BYTE *pch;
  464. FILE *pfSym;
  465. WORD seg_ptr;
  466. long symPos1, symPos2;
  467. struct mapdef MAPDEF;
  468. struct mapend MAPEND;
  469. struct segdef SEGDEF;
  470. struct symdef SYMDEF;
  471. BYTE *htoa();
  472. register int pathcnt;
  473. char symfile[65];
  474. int len;
  475. pch = stModule;
  476. cch = *pch++;
  477. pch = (BYTE *) memcpy(pchOut, pch, cch) + cch;
  478. if((len = strlen(pchOut)) < 2)
  479. return (-1);
  480. pch[0] = '.';
  481. pch[1] = 'S';
  482. pch[2] = 'Y';
  483. pch[3] = 'M';
  484. pch[4] = 0;
  485. if (bSymPath)
  486. {
  487. for (pathcnt=0; pathcnt <num_paths; pathcnt++)
  488. {
  489. strcpy(symfile, path_table[pathcnt]);
  490. strcat(symfile, "\\");
  491. strcat(symfile, pchOut);
  492. if (pfSym = fopen(symfile, "rb"))
  493. break;
  494. }
  495. }
  496. else
  497. pfSym = fopen(pchOut, "rb");
  498. /* If symbol file not found, insert/append () around name */
  499. if (pfSym == NULL)
  500. {
  501. pch = stModule;
  502. cch = *pch++;
  503. pch = (BYTE *) memcpy(pchOut+1, pch, cch) + cch;
  504. *pchOut = '(';
  505. *pch++ = ')';
  506. if (offset != 0xFFFF)
  507. *pch++ = '\t';
  508. *pch = 0;
  509. return(-1);
  510. }
  511. fread(&MAPDEF, 1, sizeof(MAPDEF), pfSym);
  512. *pch++ = '!';
  513. if (segno == 0xFF)
  514. {
  515. *pch++ = 'R';
  516. *pch++ = 'E';
  517. *pch++ = 'S';
  518. *pch++ = 'O';
  519. *pch++ = 'U';
  520. *pch++ = 'R';
  521. *pch++ = 'C';
  522. *pch++ = 'E';
  523. *pch = 0;
  524. fclose(pfSym);
  525. return(1);
  526. }
  527. if (segno >= MAPDEF.seg_cnt)
  528. goto lbNoSeg;
  529. seg_ptr = (WORD)MAPDEF.seg_ptr;
  530. fseek(pfSym, (long)-sizeof(MAPEND), 2);
  531. fread(&MAPEND, 1, sizeof(MAPEND), pfSym);
  532. if (MAPEND.ver != 3)
  533. {
  534. lbNoSeg:
  535. pch = htoa(pch, segno);
  536. *pch = 0;
  537. if (offset != 0xFFFF)
  538. {
  539. *pch++ = '\t';
  540. pch = htoa(pch, offset);
  541. *pch = 0;
  542. }
  543. fclose(pfSym);
  544. return(-2);
  545. }
  546. i = segno+1;
  547. while (i--)
  548. {
  549. if (MAPEND.rel >= 10)
  550. fseek(pfSym, (long)(seg_ptr * 16), 0);
  551. else
  552. fseek(pfSym, (long)seg_ptr, 0);
  553. fread(&SEGDEF, 1, sizeof(SEGDEF), pfSym);
  554. seg_ptr = (WORD)SEGDEF.nxt_seg;
  555. }
  556. fread(pch, 1, (int)((BYTE)SEGDEF.nam_len), pfSym);
  557. pch += SEGDEF.nam_len;
  558. *pch = 0;
  559. if (offset == 0xFFFF)
  560. {
  561. fclose(pfSym);
  562. return(1);
  563. }
  564. *pch++ = '\t';
  565. i = (WORD)SEGDEF.sym_cnt;
  566. if (i == 0)
  567. goto lbNoSym;
  568. symPos1 = 0;
  569. while (i--)
  570. {
  571. symPos2 = symPos1;
  572. symPos1 = ftell(pfSym);
  573. fread(&SYMDEF, 1, sizeof(SYMDEF), pfSym);
  574. if (i == 0 || (WORD)SYMDEF.sym_val > offset)
  575. {
  576. if ((WORD)SYMDEF.sym_val > offset)
  577. {
  578. if (symPos2 == 0)
  579. goto lbNoSym;
  580. fseek(pfSym, (long)symPos2, 0);
  581. fread(&SYMDEF, 1, sizeof(SYMDEF), pfSym);
  582. }
  583. fread(pch, 1, (int)((BYTE)SYMDEF.nam_len), pfSym);
  584. pch += SYMDEF.nam_len;
  585. if ((WORD)SYMDEF.sym_val < offset)
  586. {
  587. *pch++ = '+';
  588. pch = htoa(pch, offset - SYMDEF.sym_val);
  589. }
  590. *pch = 0;
  591. fclose(pfSym);
  592. return(1);
  593. }
  594. fseek(pfSym, (long)((BYTE)SYMDEF.nam_len), 1);
  595. }
  596. lbNoSym:
  597. pch = htoa(pch, offset);
  598. *pch = 0;
  599. fclose(pfSym);
  600. return(0);
  601. }
  602. BYTE *htoa( s, w ) /* Hexadecimal to ASCII */
  603. register BYTE *s;
  604. WORD w;
  605. {
  606. register int i;
  607. char c;
  608. i = 4;
  609. s += i;
  610. while (i--)
  611. {
  612. c = (char)(w & (WORD)0xF);
  613. w >>= 4;
  614. if (c > 9)
  615. c += 'A' - 10;
  616. else
  617. c += '0';
  618. *--s = c;
  619. }
  620. return s+4;
  621. }
  622.