stktrace.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:5k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /* This file contains code to print function/arg stack tracebacks
  2.  * at run time, which is extremely useful for finding heap free() errors.
  3.  *
  4.  * This code is highly specific to Borland C and the 80x6 machines.
  5.  *
  6.  * April 10, 1992 P. Karn
  7.  */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <dos.h>
  11. #include <string.h>
  12. #include <time.h>
  13. #include "global.h"
  14. #include "proc.h"
  15. struct symtab {
  16. struct symtab *next;
  17. unsigned short seg;
  18. unsigned short offs;
  19. char *name;
  20. };
  21. static struct symtab *Symtab;
  22. static void rdsymtab(int unused,void *name,void *p);
  23. static void clrsymtab(void);
  24. static struct symtab *findsym(void (*)());
  25. static int scompare();
  26. static void paddr(void (*pc)());
  27. static unsigned short Codeseg;
  28. void
  29. stktrace()
  30. {
  31. int i,j;
  32. unsigned short far *context;
  33. unsigned short far *cnext;
  34. unsigned short far *ctmp;
  35. void (*pc)();
  36. int nargs;
  37. struct proc *rdproc;
  38. struct symtab *sp;
  39. extern char **_argv;
  40. char *mapname;
  41. char *cp;
  42. FILE *fp,*outsave;
  43. time_t t;
  44. /* Temporarily redirect stdout to file */
  45. if((fp = fopen("stktrace.out","at")) == NULL)
  46. return; /* Give up */
  47. outsave = Curproc->output;
  48. Curproc->output = fp;
  49. time(&t);
  50. printf("stktrace from proc %s at %s",Curproc->name,ctime(&t));
  51. Codeseg = _psp + 0x10;
  52. #ifdef notdef
  53. printf("Code base segment: %xn",Codeseg);
  54. #endif
  55. /* Construct name of map file */
  56. mapname = malloc(strlen(_argv[0]) + 5);
  57. strcpy(mapname,_argv[0]);
  58. if((cp = strrchr(mapname,'.')) != NULL)
  59. *cp = '';
  60. strcat(mapname,".map");
  61. /* Read the symbol table in another process to avoid overstressing
  62.  * the stack in this one
  63.  */
  64. rdproc = newproc("rdsymtab",512,rdsymtab,1,mapname,NULL,0);
  65. kwait(rdproc);
  66. free(mapname);
  67. context = MK_FP(_SS,_BP);
  68. pc = stktrace;
  69. for(i=0;i<20;i++){
  70. paddr(pc);
  71. sp = findsym(pc);
  72. if(sp != NULL)
  73. printf(" %s+%x",sp->name,FP_OFF(pc) - sp->offs);
  74. if(FP_OFF(context) == 0){
  75. /* No context left, we're done */
  76. putchar('n');
  77. break;
  78. }
  79. cnext = MK_FP(FP_SEG(context),*context);
  80. /* Compute number of args to display */
  81. if(FP_OFF(cnext) != 0){
  82. nargs = cnext - context - (1 + sizeof(pc)/2);
  83. if(nargs > 20)
  84. nargs = 20; /* limit to reasonable number */
  85. } else {
  86. /* No higher level context, so just print an
  87.  * arbitrary fixed number of args
  88.  */
  89. nargs = 6;
  90. }
  91. /* Args start after saved BP and return address */
  92. ctmp = context + 1 + sizeof(pc)/2;
  93. printf("(");
  94. for(j=0;j<nargs;j++){
  95. fprintf(fp,"%x",*ctmp);
  96. if(j < nargs-1)
  97. putchar(' ');
  98. else
  99. break;
  100. ctmp++;
  101. }
  102. printf(")n");
  103. #ifdef notdef
  104. if(strcmp(cp,"_main") == 0)
  105. break;
  106. #endif
  107. #ifdef LARGECODE
  108. pc = MK_FP(context[2],context[1]);
  109. #else
  110. pc = (void (*)())MK_FP(FP_SEG(pc),context[1]);
  111. #endif
  112. context = cnext;
  113. }
  114. clrsymtab();
  115. fclose(fp);
  116. Curproc->output = outsave;
  117. }
  118. static struct symtab *
  119. findsym(pc)
  120. void (*pc)();
  121. {
  122. struct symtab *sp,*spprev;
  123. unsigned short seg,offs;
  124. #ifdef LARGECODE
  125. seg = FP_SEG(pc) - Codeseg;
  126. #else
  127. seg = 0; /* Small code, no segment */
  128. #endif
  129. offs = FP_OFF(pc);
  130. spprev = NULL;
  131. for(sp = Symtab;sp != NULL;spprev = sp,sp = sp->next){
  132. if(sp->seg > seg || (sp->seg == seg && sp->offs > offs)){
  133. break;
  134. }
  135. }
  136. return spprev;
  137. }
  138. static void
  139. clrsymtab()
  140. {
  141. struct symtab *sp,*spnext;
  142. for(sp = Symtab;sp != NULL;sp = spnext){
  143. spnext = sp->next;
  144. free(sp->name);
  145. free(sp);
  146. }
  147. Symtab = NULL;
  148. }
  149. static void
  150. rdsymtab(unused,name,p)
  151. int unused;
  152. void *name;
  153. void *p;
  154. {
  155. char *buf;
  156. FILE *fp;
  157. unsigned short seg;
  158. unsigned short offs;
  159. struct symtab *sp;
  160. struct symtab **spp;
  161. int size = 0;
  162. int i;
  163. if((fp = fopen(name,"rt")) == NULL){
  164. printf("can't read %sn",name);
  165. return;
  166. }
  167. buf = (char *)malloc(128);
  168. while(fgets(buf,128,fp),!feof(fp)){
  169. rip(buf);
  170. if(strcmp(buf,"  Address         Publics by Value") == 0)
  171. break;
  172. }
  173. if(feof(fp)){
  174. printf("Can't find header line in %sn",name);
  175. free(buf);
  176. return;
  177. }
  178. Symtab = NULL;
  179. while(fgets(buf,128,fp),!feof(fp)){
  180. rip(buf);
  181. if(sscanf(buf,"%x:%x",&seg,&offs) != 2)
  182. continue;
  183. sp = (struct symtab *)malloc(sizeof(struct symtab));
  184. sp->offs = offs;
  185. sp->seg = seg;
  186. sp->name = strdup(buf+17);
  187. sp->next = Symtab;
  188. Symtab = sp;
  189. size++;
  190. }
  191. fclose(fp);
  192. free(buf);
  193. #ifdef notdef
  194. printf("Symbols read: %dn",size);
  195. #endif
  196. /* Sort the symbols using the quicksort library function */
  197. spp = malloc(size*sizeof(struct symtab *));
  198. for(i=0,sp = Symtab;sp != NULL;i++,sp = sp->next)
  199. spp[i] = sp;
  200. qsort(spp,size,sizeof(struct symtab *),scompare);
  201. /* Now put them back in the linked list */
  202. Symtab = NULL;
  203. for(i=size-1;i >= 0;i--){
  204. sp = spp[i];
  205. sp->next = Symtab;
  206. Symtab = sp;
  207. }
  208. free(spp);
  209. #ifdef notdef
  210. for(sp = Symtab;sp != NULL;sp = sp->next)
  211. printf("%x:%x %sn",sp->seg,sp->offs,sp->name);
  212. #endif
  213. }
  214. static int
  215. scompare(a,b)
  216. struct symtab **a,**b;
  217. {
  218. if((*a)->seg > (*b)->seg)
  219. return 1;
  220. if((*a)->seg < (*b)->seg)
  221. return -1;
  222. if((*a)->offs > (*b)->offs)
  223. return 1;
  224. if((*a)->offs < (*b)->offs)
  225. return -1;
  226. return 0;
  227. }
  228. /* Print a code address according to the memory model */
  229. static void
  230. paddr(pc)
  231. void (*pc)();
  232. {
  233. #ifdef LARGECODE
  234. printf("%04x:%04x",FP_SEG(pc) - Codeseg,FP_OFF(pc));
  235. #else
  236. printf("%04x",FP_OFF(pc);
  237. #endif
  238. }