Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Stack trace in C/C++

32 views
Skip to first unread message

Chabane Rezzik

unread,
Jul 30, 1999, 3:00:00 AM7/30/99
to
Hi there,

Is there anyway I can dump the stack without aborting the process?

Please copy my e-mail when replying.

Thanks a lot,
Chabane


Michel Bardiaux

unread,
Jul 31, 1999, 3:00:00 AM7/31/99
to

That depends largely on the platform; not just the CPU, but also the
details of executable images. I know of a 75% solution for SGI IRIX
(dumps
the list of return adresses with the corresponding procedure names
but NOT the source file name and line numbers). I know of a partial
solution for LINUX (dumps the call sites, but the translation to
function name has to be done out of the app). And I know the API exists
for Wintel, but I did not look into it yet.

I hasten to say, I am not the *author* of these solutions; I am simply
in the process of gathering that info for several platforms.

If you could give details of your target(s) we might cooperate on this.

Greetings.
--
Michel Bardiaux
UsrConsult S.P.R.L. Rue Margot, 37 B-1457 Nil St Vincent
Tel : +32 10 65.44.15 Fax : +32 10 65.44.10

Andrew Gabriel

unread,
Jul 31, 1999, 3:00:00 AM7/31/99
to
In article <37A2CD59...@usrconsult.be>,

Michel Bardiaux <mbar...@usrconsult.be> writes:
>Chabane Rezzik wrote:
>>
>> Hi there,
>>
>> Is there anyway I can dump the stack without aborting the process?
>>
>> Please copy my e-mail when replying.
>>
>> Thanks a lot,
>> Chabane
>
>That depends largely on the platform; not just the CPU, but also the
>details of executable images. I know of a 75% solution for SGI IRIX
>(dumps
>the list of return adresses with the corresponding procedure names
>but NOT the source file name and line numbers). I know of a partial
>solution for LINUX (dumps the call sites, but the translation to
>function name has to be done out of the app). And I know the API exists
>for Wintel, but I did not look into it yet.

Sun have provided an API and demo program with Solaris 7
(but I'm currently sitting at an earlier Solaris, and I
can't remember where it is or what it's called, sorry :-).

--
Andrew Gabriel
Consultant Software Engineer


stanislav shalunov

unread,
Jul 31, 1999, 3:00:00 AM7/31/99
to
Chabane Rezzik <cre...@aud.alcatel.com> writes:

> Is there anyway I can dump the stack without aborting the process?

If you just need the stack trace (not core dump), you can notice the
PID of the process you want, fire up gdb (without arguments), then use
"attach PID" command, then do a "bt". If you need a core dump without
aborting, you should talk to your Unix vendor.

markku.l...@hybrid.fi

unread,
Aug 1, 1999, 3:00:00 AM8/1/99
to cre...@aud.alcatel.com
In article <37A21679...@aud.alcatel.com>,
Chabane Rezzik <cre...@aud.alcatel.com> wrote:
> Hi there,

>
> Is there anyway I can dump the stack without aborting the process?

Yes, there is. You have to take a look for the stack & backward call
chain. You could take a look for the source code of some of the debug
malloc implementations (dmalloc ?) to see how this can be done is
several platforms.

PKY


>
> Please copy my e-mail when replying.
>
> Thanks a lot,
> Chabane
>
>


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.

Bjorn Reese

unread,
Aug 2, 1999, 3:00:00 AM8/2/99
to
Chabane Rezzik wrote:

> Is there anyway I can dump the stack without aborting the process?

http://www.mip.sdu.dk/~breese/debug/stacktrace.c

Andrew Gabriel

unread,
Aug 3, 1999, 3:00:00 AM8/3/99
to
In article <87zp0ce...@sharik.worldnet.att.net>,

stanislav shalunov <shal...@att.com> writes:
>If you need a core dump without
>aborting, you should talk to your Unix vendor.

fork and abort in the child.

Also, man gcore(1) (if your platform has it).

Michel Bardiaux

unread,
Aug 3, 1999, 3:00:00 AM8/3/99
to
OK, there are lots of ways to obtain a stack trace using dbx/gdb in
various
smart ways. Thanks to all who sent suggestions.

But what is the state-of-the-art regarding traces obtained using *only*
code
in the executable? That is, in a production and not development
environment.
To summarize, the question is "Where am I coming from" (address,
function name, source file
name and line number, recursively); and the rules of the game are
(1) No crash, proggy goes on (2) No external tool (no gdb).

From some searches I made recently on the Web and in News archives, it
seems
there a few solutions and none is complete. I found something for LINUX
(addresses
only), IRIX (addresses and function name) and WINTEL (did not look
closely yet).
Who has more?

Erik Pras

unread,
Aug 3, 1999, 3:00:00 AM8/3/99
to
Michel,

On HP-UX you can call U_STACK_TRACE(), which prints the stack to stderr.

A way print it to a file this was posted in the HP Ansi C++ mailing list
about half a year ago:

#include <unistd.h>
#include <stdio.h>
extern void U_STACK_TRACE(void);
void redirect_stack_trace(FILE *filest) {
int fd, fd2, err;
fd = fileno(filest);
fflush(filest);
fflush(stderr);
fd2 = dup(STDERR_FILENO);
err = dup2(fd, STDERR_FILENO);
U_STACK_TRACE();
fflush(stderr);
fd = dup2(fd2, STDERR_FILENO);
close(fd2);
}

Hope this helps,

Erik


Frank Pilhofer

unread,
Aug 3, 1999, 3:00:00 AM8/3/99
to
In article <7o0l39$a0v$1...@nnrp1.deja.com>, markku.l...@hybrid.fi wrote:
> In article <37A21679...@aud.alcatel.com>,
> Chabane Rezzik <cre...@aud.alcatel.com> wrote:
> > Hi there,
> >
> > Is there anyway I can dump the stack without aborting the process?
>
> Yes, there is. You have to take a look for the stack & backward call
> chain. You could take a look for the source code of some of the debug
> malloc implementations (dmalloc ?) to see how this can be done is
> several platforms.
>

I've been through this for my MemTrace package, which records a stack
trace with each allocated chunk of memory. So far, it works on Linux and
SunOS. See http://www.informatik.uni-frankfurt.de/~fp/Tools/MemTrace/
It provides functions for recording a call stack and printing it in a
symbolic way.

Frank


--
+ Frank Pilhofer f...@informatik.uni-frankfurt.de +
| http://www.uni-frankfurt.de/~fp/ |
+---- Life would be a very great deal less weird without you. - DA ----+

Andrew Gabriel

unread,
Aug 4, 1999, 3:00:00 AM8/4/99
to
[crossposted to comp.unix.solaris]

Michel Bardiaux <mbar...@usrconsult.be> wrote:
>OK, there are lots of ways to obtain a stack trace using dbx/gdb in
>various
>smart ways. Thanks to all who sent suggestions.
>
>But what is the state-of-the-art regarding traces obtained using *only*
>code
>in the executable? That is, in a production and not development
>environment.

Here's part (which I think should work by itself) of a backtrace
I have built up for Solaris over a few years, incorporating odd
tidbits posted to newsgroups. I have stripped this out of a much
larger file which copes with Solaris 2.3 (no dladdr()), but as
long as you're using Solaris 2.4 or later, this is all you need.

Almost certainly won't work in 64 bit mode - I havn't tried.
However, note as I said before that Sun now include a demo
program and library with Solaris 7 which does this anyway.

It would be nice to add support for compiler debug info, but I
havn't had time to work out how to do this.

/* ......................................................................... */

/* Produce a stack trace for Solaris systems. */

/* Copyright (C) 1995-1998 Andrew Gabriel <and...@cucumber.demon.co.uk>
Parts derived from Usenet postings of Bart Smaalders and Casper Dik.
*/

/* ......................................................................... */

#include <setjmp.h>
#include <sys/types.h>
#include <sys/reg.h>
#include <sys/frame.h>
#include <dlfcn.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>

#if defined(sparc) || defined(__sparc)
#define FLUSHWIN() asm("ta 3");
#define FRAME_PTR_INDEX 1
#define SKIP_FRAMES 0
#endif

#if defined(i386) || defined(__i386)
#define FLUSHWIN()
#define FRAME_PTR_INDEX 3
#define SKIP_FRAMES 1
#endif

#if defined(ppc) || defined(__ppc)
#define FLUSHWIN()
#define FRAME_PTR_INDEX 0
#define SKIP_FRAMES 2
#endif

/* ......................................................................... */

static void print_address(void *pc)
{
Dl_info info;

if (dladdr(pc, &info) == 0)
{
/* not found */

fprintf(stderr, "*** %s:0x%x\n",
"??",
(unsigned int)pc);
}
else
{
/* found */

fprintf(stderr, "*** %s:%s+0x%x\n",
info.dli_fname,
info.dli_sname,
(unsigned int)pc - (unsigned int)info.dli_saddr);
}

return;
}

/* ......................................................................... */

static int validaddr(void *addr)
{
static long pagemask = -1;
char c;

if (pagemask == -1)
pagemask = ~(sysconf(_SC_PAGESIZE) - 1);

addr = (void *)((long)addr & pagemask);
if (mincore((char*) addr, 1, &c) == -1 && errno == ENOMEM)
return 0; /* invalid */
else
return 1; /* valid */
}

/* ......................................................................... */

/*
this function walks up call stack, calling print_addess
once for each stack frame, passing the pc as the argument.
*/

static void print_stack(void)
{
struct frame *sp;
jmp_buf env;
int i;
int * iptr;

FLUSHWIN();

setjmp(env);
iptr = (int*) env;

sp = (struct frame *) iptr[FRAME_PTR_INDEX];

for (i=0; i<SKIP_FRAMES && sp; i++)
{
if (!validaddr(sp) || !validaddr(&sp->fr_savpc))
{
fprintf(stderr, "***[stack pointer corrupt]\n" );
return;
}
sp = (struct frame *)sp->fr_savfp;
}

i = 100; /* looping check */

while (validaddr(sp) && validaddr(&sp->fr_savpc) && sp->fr_savpc && --i )
{
print_address((void*)sp->fr_savpc);
sp = (struct frame *)sp->fr_savfp;
}
}

/* ......................................................................... */

void backtrace( void )
{
fprintf(stderr, "***backtrace...\n" );
print_stack();
fprintf(stderr, "***backtrace ends\n" );
}

/* ......................................................................... */

0 new messages