delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2012/03/12/05:40:01

X-Recipient: archive-cygwin AT delorie DOT com
X-SWARE-Spam-Status: No, hits=-1.4 required=5.0 tests=AWL,BAYES_00,T_RP_MATCHES_RCVD
X-Spam-Check-By: sourceware.org
MIME-Version: 1.0
Subject: Unfolding the stack
Date: Mon, 12 Mar 2012 10:39:05 +0100
Message-ID: <6BFA9AF2C7556E42AFF3F187ECAB07B802DAFBAB@bespdc01.mediaxim.local>
From: "Michel Bardiaux" <MBardiaux AT mediaxim DOT be>
To: <cygwin AT cygwin DOT com>
X-IsSubscribed: yes
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com
X-MIME-Autoconverted: from quoted-printable to 8bit by delorie.com id q2C9duaX020164

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


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019