This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Unfolding the stack


To complete the port of some library to Cygwin, I need a way to produce
a traceback with as much info as possible. Currently I have something
that works but not that well.  There are basically 3 parts:

* Gather all the stack frames; see below.
* Assign the PCs in each frame to some executable image; done via dlfcn.
To be discussed later.
* Convert the PCs to function+source+line; done via addr2line. Ditto.

Despite a lot of web digging I have not (yet?) found a better way than
this classic unixish song-and-dance:

int
backtrace(void** buf, int bufsiz)
{
	int		res;
	int	 	p[2];
	pid_t		child;
	FILE*		thePipe = (NULL);
	char		line[1024];
	void*		unused;
	if (pipe(p) < 0){
		debug(-1, "*** Pipe() failed\n");
		return -1;
	}
	if ((child=fork())<0) {
		debug(-1, "*** Fork() failed\n");
		return -1;
	} else if (child == 0) {
		// In child. Make p[1] its stderr
		close(0);
		close(1);
		dup2 (p[1], 2);
		close (p[0]);
		close (p[1]);
		cygwin_stackdump();
		exit(0);
	}
	// In our process. Read from the pipe.
	close (p[1]);
	if((thePipe=fdopen(p[0], "rb"))==NULL) {
		debug(-1, "*** fdopen failed\n");
		return -1;
	}
	res = 0;
	while(fgets(line, sizeof(line), thePipe)) {
		if(res>=bufsiz)
			break;
		while(isspace(line[strlen(line)-1]))
			line[strlen(line)-1]=0;
		if(strcmp(line, "Stack trace:")==0 ||
			strncmp(line, "Frame", 5)==0)
			continue;
		if(strcmp(line, "End of stack trace")==0)
			break;
		if(sscanf(line, "%8X %8X", (int*)&unused,
(int*)(buf+res))!=2) {
			debug(-1, "*** sscanf failed\n");
			return -1;
		}
		res++;
	}
	fclose(thePipe);
	return res;
}

Where debug(-1,...) is essentially fprintf(stderr,...).

Now this is acceptable for a traceback following the raising of some
error condition, but seems much too heavy for using in a leak detector.
Does anyone know of an equivalent API under cygwin? Or could we consider
adding such a variation of cygwin_stackdump to the cygwin DLL?

TiA
Michel Bardiaux

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]