Date: Thu, 8 Jan 1998 10:53:54 +0200 (IST) From: Eli Zaretskii To: Shaun Jackman cc: djgpp AT delorie DOT com Subject: Re: GNU Profiler bug In-Reply-To: <34B448BB.97D6B7EC@rogers.wave.ca> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk On Wed, 7 Jan 1998, Shaun Jackman wrote: > It says in the patch there is a patch available to fix the bug. > (any program compiled with -pg crashes in Win95) > > I can't seem to find the patch anywhere though, can someone please tell > me where I can find it, and what its file name would be? The FAQ also says that you can find the patch by searching the DJGPP mail archives. To search the archives, point your Web browser to the http://www.delorie.com/djgpp/mail-archives/ and use keywords to find relevant discussions. That is how you should have found the patch. The patched file mcount.c that is the reason for the crashes is attached to this message. You need to compile it and put it into your library, like this: gcc -O3 -c mcount.c ar rvs c:/djgpp/lib/libc.a mcount.o (the full pathname of libc.a might be different on your system). Then relink your program with the patched library, and the crashes should go away. If they don't please report the details (stack dump printed when it crashes, etc.). ----------------------------------------------------------------- /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include #include #include #include #include #include #include #include #include /* header of a GPROF type file */ typedef struct { long low; long high; long nbytes; } header; /* entry of a GPROF type file */ typedef struct { unsigned long from; unsigned long to; unsigned long count; } MTABE; /* internal form - sizeof(MTAB) is 4096 for efficiency */ typedef struct MTAB { MTABE calls[341]; struct MTAB *prev; } MTAB; static header h; static short *histogram; static int mcount_skip = 1; static int histlen; static MTAB *mtab=0; extern int etext; /* called by functions. Use the pointer it provides to cache ** the last used MTABE, so that repeated calls to/from the same ** pair works quickly - no lookup. */ void mcount(int _to); void mcount(int _to) { MTAB *m; int i; int to; int ebp; int from; int mtabi; MTABE **cache; if (&_to < &etext) *(int *)(-1) = 0; /* fault! */ mcount_skip = 1; asm("movl %%edx,%0" : "=g" (cache)); /* obtain the cached pointer */ to = *((&_to)-1) - 12; ebp = *((&_to)-2); /* glean the caller's return address from the stack */ from = ((int *)ebp)[1]; if (*cache && ((*cache)->from == from) && ((*cache)->to == to)) { /* cache paid off - works quickly */ (*cache)->count++; mcount_skip = 0; return; } /* no cache hit - search all mtab tables for a match, or an empty slot */ mtabi = -1; for (m=mtab; m; m=m->prev) { for (i=0; i<341; i++) { if (m->calls[i].from == 0) { /* empty slot - end of table */ mtabi = i; break; } if ((m->calls[i].from == from) && (m->calls[i].to == to)) { /* found a match - bump count and return */ m->calls[i].count ++; *cache = m->calls + i; mcount_skip = 0; return; } } } if (mtabi != -1) { /* found an empty - fill it in */ mtab->calls[mtabi].from = from; mtab->calls[mtabi].to = to; mtab->calls[mtabi].count = 1; *cache = mtab->calls + mtabi; mcount_skip = 0; return; } /* lob off another page of memory and initialize the new table */ m = (MTAB *)sbrk(sizeof(MTAB)); memset(m, 0, sizeof(MTAB)); m->prev = mtab; mtab = m; m->calls[0].from = from; m->calls[0].to = to; m->calls[0].count = 1; *cache = m->calls; mcount_skip = 0; } /* this is called during program exit (installed by atexit). */ static void mcount_write(void) { MTAB *m; int i, f; struct itimerval new_values; mcount_skip = 1; /* disable timer */ new_values.it_value.tv_usec = new_values.it_interval.tv_usec = 0; new_values.it_value.tv_sec = new_values.it_interval.tv_sec = 0; setitimer(ITIMER_PROF, &new_values, NULL); f = open("gmon.out", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666); write(f, &h, sizeof(header)); write(f, histogram, histlen); for (m=mtab; m; m=m->prev) { for (i=0; i<341; i++) if (m->calls[i].from == 0) break; write(f, m->calls, i*12); } close(f); } extern unsigned start __asm__ ("start"); #define START (unsigned)&start extern int etext; /* ARGSUSED */ static void mcount_tick(int _x) { unsigned bin; if(!mcount_skip) { bin = __djgpp_exception_state->__eip; if(bin >= START && bin <= (unsigned)&etext) { bin = (bin - START) / 4; /* 4 EIP's per bin */ histogram[bin]++; } } } /* this is called to initialize profiling before the program starts */ void _mcount_init(void); void _mcount_init(void) { struct itimerval new_values; h.low = START; h.high = (int)&etext; histlen = (h.high-h.low)/4*sizeof(short); h.nbytes = sizeof(header) + histlen; histogram = (short *)sbrk(histlen); memset(histogram, 0, histlen); atexit(mcount_write); /* here, do whatever it takes to initialize the timer interrupt */ signal(SIGPROF, mcount_tick); /* 18.2 tics per second */ new_values.it_value.tv_usec = new_values.it_interval.tv_usec = 5494; new_values.it_value.tv_sec = new_values.it_interval.tv_sec = 0; setitimer(ITIMER_PROF, &new_values, NULL); mcount_skip = 0; }