Unix Technical Forum

Getting call stack (like dbx where cmd)

This is a discussion on Getting call stack (like dbx where cmd) within the AIX Operating System forums, part of the Unix Operating Systems category; --> Is there a way (understandably non-portable) to get the call stack from within a function? That is, assuming the ...


Go Back   Unix Technical Forum > Unix Operating Systems > AIX Operating System

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 01-05-2008, 03:34 AM
Adrian
 
Posts: n/a
Default Getting call stack (like dbx where cmd)

Is there a way (understandably non-portable) to get the
call stack from within a function? That is, assuming the
application has been compiled with symbols, get the list
of calling function names (similar to dbx "where" command").

I am working with IBM compiler and AIX but any other
OS/compiler solution would be interesting as well.

To answer the inevitable question why I want this,
I am writing a simple profiler for my library. However,
within the library I want to distinguish which part of
the application I was called from....

Thanks for any ideas or pointers,
Adrian
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 01-05-2008, 03:34 AM
Paul Pluzhnikov
 
Posts: n/a
Default Re: Getting call stack (like dbx where cmd)

Adrian <notvalid@null.net> writes:

> Is there a way (understandably non-portable) to get the
> call stack from within a function?


Sure: if dbx can do it, so can you.

> To answer the inevitable question why I want this,
> I am writing a simple profiler for my library. However,
> within the library I want to distinguish which part of
> the application I was called from....


Why not pass a parameter?

> Thanks for any ideas or pointers,


Look for POWERPC parts here:
http://cvs.sourceforge.net/viewcvs.p...ol/src/stack.c

This is off-topic in comp.lang.c (I think).
Followup-to comp.unix.aix

Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 01-05-2008, 03:34 AM
CBFalconer
 
Posts: n/a
Default Re: Getting call stack (like dbx where cmd)

Adrian wrote:
>
> Is there a way (understandably non-portable) to get the
> call stack from within a function? That is, assuming the
> application has been compiled with symbols, get the list
> of calling function names (similar to dbx "where" command").
>
> I am working with IBM compiler and AIX but any other
> OS/compiler solution would be interesting as well.
>
> To answer the inevitable question why I want this,
> I am writing a simple profiler for my library. However,
> within the library I want to distinguish which part of
> the application I was called from....


Since you know the CPU things are running on, it should not be hard
to write a couple of callable assembly language routines to return
those values. Something like:

void *getbp(void);
void *getsp(void);

They might even be implemented as inline, since they should be very
short, and that will avoid complications of digging into the
stack. getbp would probable resolve to "mov ax,bp".

Implementation is OT here, however how they should be integrated
into a C program is not.

--
Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!


Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #4 (permalink)  
Old 01-05-2008, 03:35 AM
Shaun Clowes
 
Posts: n/a
Default Re: Getting call stack (like dbx where cmd)


"Adrian" <notvalid@null.net> wrote in message
news:10o52t92hdgik76@news.supernews.com...
> I am working with IBM compiler and AIX but any other
> OS/compiler solution would be interesting as well.


Well, since this completely OS/Architecture specific you'll generally have
to search newsgroups for solutions for the specific platforms you're looking
for. Anyways, for AIX it'll look something like this:

void FaultHandler(int iSignal, siginfo_t *ptSigInfo, void *pvSomething)
{
DumpCallStack(1, (ucontext_t *) pvSomething);
}

void DumpCallStack(int iFd, ucontext_t *ptContext)

void *pvInstructionPointer;
void **ppvStackFrame;
int iFrame = 0;

/* The standard stack layout for a process on the PowerPC architecture
(AIX ABI) when a() has called b() which called c() looks
like the following:

--------------------------------
-- | Saved Stack Pointer | <-- Stack pointer (%R1/SP)
| | Saved Control Register |
| | Saved Location Register | Not used until call out of
C()
| --------------------------------
| | |
| | Local Variables for c() |
| | |
| --------------------------------
-> | Saved Stack Pointer | --
| Saved Control Register | |
| Saved Location Register | | Saved by c() containing
location
-------------------------------- | or call from b()
| | |
| Local Variables for b() | |
| | |
-------------------------------- |
| Saved Stack Pointer | <-
| Saved Control Register |
| Saved Location Register | Saved by b() containing
location
-------------------------------- or call from a()
| |
| Local Variables for a() |
| |
--------------------------------

Refer to the PowerPC Compiler Writer's Guide or the AIX Assembly
Language
Reference for more information */
sprintf(sString, "Faulted while executing instruction at 0x%08x\n"
"\n"
"Traceback:\n",
ptContext->uc_mcontext.jmp_context.iar);
write(iFd, sString, strlen(sString));

/* Roll down the stack frames */
pvInstructionPointer = (void *) ptContext->uc_mcontext.jmp_context.iar;
ppvStackFrame = (void **) ptContext->uc_mcontext.jmp_context.gpr[1];
do
{
sprintf(sString, "(%2d) 0x%p\n", iFrame, pvInstructionPointer);
write(iFd, sString, strlen(sString));

/* Have we hit the bottom of the stack? */
if (!ppvStackFrame[0])
break;

/* Validate the stack frame before using any portion of it */
if (!ValidAddress((void *) ppvStackFrame) ||
!ValidAddress((void *) ppvStackFrame[0]) ||
!ValidAddress((void *) ((void **) ppvStackFrame[0] + 2)))
{
sprintf(sString, "Invalid frame at %p\n", (void *) ppvStackFrame);
write(iFd, sString, strlen(sString));
break;
}

ppvStackFrame = (void **) ppvStackFrame[0];
pvInstructionPointer = ppvStackFrame[2];
iFrame++;
} while(ppvStackFrame);

Cheers,
Shaun


Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #5 (permalink)  
Old 01-05-2008, 03:35 AM
T.R.Bennett
 
Posts: n/a
Default Re: Getting call stack (like dbx where cmd)

"Shaun Clowes" <delius@no.spam.for.me.progsoc.org> wrote in message news:<ETehd.10$fj3.808@nnrp1.ozemail.com.au>...
> "Adrian" <notvalid@null.net> wrote in message
> news:10o52t92hdgik76@news.supernews.com...
> > I am working with IBM compiler and AIX but any other
> > OS/compiler solution would be interesting as well.

>
> Well, since this completely OS/Architecture specific you'll generally have
> to search newsgroups for solutions for the specific platforms you're looking
> for. Anyways, for AIX it'll look something like this:
>
> void FaultHandler(int iSignal, siginfo_t *ptSigInfo, void *pvSomething)
> {
> DumpCallStack(1, (ucontext_t *) pvSomething);
> }
>
> void DumpCallStack(int iFd, ucontext_t *ptContext)
>
> void *pvInstructionPointer;
> void **ppvStackFrame;
> int iFrame = 0;
>
> /* The standard stack layout for a process on the PowerPC architecture
> (AIX ABI) when a() has called b() which called c() looks
> like the following:
>
> --------------------------------
> -- | Saved Stack Pointer | <-- Stack pointer (%R1/SP)
> | | Saved Control Register |
> | | Saved Location Register | Not used until call out of
> C()
> | --------------------------------
> | | |
> | | Local Variables for c() |
> | | |
> | --------------------------------
> -> | Saved Stack Pointer | --
> | Saved Control Register | |
> | Saved Location Register | | Saved by c() containing
> location
> -------------------------------- | or call from b()
> | | |
> | Local Variables for b() | |
> | | |
> -------------------------------- |
> | Saved Stack Pointer | <-
> | Saved Control Register |
> | Saved Location Register | Saved by b() containing
> location
> -------------------------------- or call from a()
> | |
> | Local Variables for a() |
> | |
> --------------------------------
>
> Refer to the PowerPC Compiler Writer's Guide or the AIX Assembly
> Language
> Reference for more information */
> sprintf(sString, "Faulted while executing instruction at 0x%08x\n"
> "\n"
> "Traceback:\n",
> ptContext->uc_mcontext.jmp_context.iar);
> write(iFd, sString, strlen(sString));
>
> /* Roll down the stack frames */
> pvInstructionPointer = (void *) ptContext->uc_mcontext.jmp_context.iar;
> ppvStackFrame = (void **) ptContext->uc_mcontext.jmp_context.gpr[1];
> do
> {
> sprintf(sString, "(%2d) 0x%p\n", iFrame, pvInstructionPointer);
> write(iFd, sString, strlen(sString));
>
> /* Have we hit the bottom of the stack? */
> if (!ppvStackFrame[0])
> break;
>
> /* Validate the stack frame before using any portion of it */
> if (!ValidAddress((void *) ppvStackFrame) ||
> !ValidAddress((void *) ppvStackFrame[0]) ||
> !ValidAddress((void *) ((void **) ppvStackFrame[0] + 2)))
> {
> sprintf(sString, "Invalid frame at %p\n", (void *) ppvStackFrame);
> write(iFd, sString, strlen(sString));
> break;
> }
>
> ppvStackFrame = (void **) ppvStackFrame[0];
> pvInstructionPointer = ppvStackFrame[2];
> iFrame++;
> } while(ppvStackFrame);
>
> Cheers,
> Shaun



Thanks for the tips Shaun, however you didn't define the
function "ValidAddress()".

-tony
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #6 (permalink)  
Old 01-05-2008, 03:35 AM
Shaun Clowes
 
Posts: n/a
Default Re: Getting call stack (like dbx where cmd)


"T.R.Bennett" <bennett.tony@cnf.com> wrote in message
news:2028e6a0.0411011153.3c426bc5@posting.google.c om...
> "Shaun Clowes" <delius@no.spam.for.me.progsoc.org> wrote in message

news:<ETehd.10$fj3.808@nnrp1.ozemail.com.au>...
> > "Adrian" <notvalid@null.net> wrote in message
> > news:10o52t92hdgik76@news.supernews.com...
> > > I am working with IBM compiler and AIX but any other
> > > OS/compiler solution would be interesting as well.

> >
> > Well, since this completely OS/Architecture specific you'll generally

have
> > to search newsgroups for solutions for the specific platforms you're

looking
> > for. Anyways, for AIX it'll look something like this:

....
> Thanks for the tips Shaun, however you didn't define the
> function "ValidAddress()".


True, here goes:

int ValidAddress(void *pvAddr)
{
int iRet = 1;

/* We could also use lchown() and probably a number of others,
* we just need a system call which takes in a userland pointer
* and doesn't change any important process context */
if (access((char *) pvAddr, F_OK) && (errno == EFAULT))
iRet = 0;

return(iRet);
}

Some people prefer mincore(2).

Cheers,
Shaun


Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #7 (permalink)  
Old 01-05-2008, 03:36 AM
Adrian
 
Posts: n/a
Default Re: Getting call stack (like dbx where cmd)

Shaun Clowes wrote:
> "Adrian" <notvalid@null.net> wrote in message
> news:10o52t92hdgik76@news.supernews.com...
>
>>I am working with IBM compiler and AIX but any other
>>OS/compiler solution would be interesting as well.

>
>
> Well, since this completely OS/Architecture specific you'll generally have
> to search newsgroups for solutions for the specific platforms you're looking
> for. Anyways, for AIX it'll look something like this:
>
> void FaultHandler(int iSignal, siginfo_t *ptSigInfo, void *pvSomething)
> {
> DumpCallStack(1, (ucontext_t *) pvSomething);
> }
>
> void DumpCallStack(int iFd, ucontext_t *ptContext)
>
> void *pvInstructionPointer;
> void **ppvStackFrame;
> int iFrame = 0;
>
> /* The standard stack layout for a process on the PowerPC architecture
> (AIX ABI) when a() has called b() which called c() looks
> like the following:
>
> --------------------------------
> -- | Saved Stack Pointer | <-- Stack pointer (%R1/SP)
> | | Saved Control Register |
> | | Saved Location Register | Not used until call out of
> C()
> | --------------------------------
> | | |
> | | Local Variables for c() |
> | | |
> | --------------------------------
> -> | Saved Stack Pointer | --
> | Saved Control Register | |
> | Saved Location Register | | Saved by c() containing
> location
> -------------------------------- | or call from b()
> | | |
> | Local Variables for b() | |
> | | |
> -------------------------------- |
> | Saved Stack Pointer | <-
> | Saved Control Register |
> | Saved Location Register | Saved by b() containing
> location
> -------------------------------- or call from a()
> | |
> | Local Variables for a() |
> | |
> --------------------------------
>
> Refer to the PowerPC Compiler Writer's Guide or the AIX Assembly
> Language
> Reference for more information */
> sprintf(sString, "Faulted while executing instruction at 0x%08x\n"
> "\n"
> "Traceback:\n",
> ptContext->uc_mcontext.jmp_context.iar);
> write(iFd, sString, strlen(sString));
>
> /* Roll down the stack frames */
> pvInstructionPointer = (void *) ptContext->uc_mcontext.jmp_context.iar;
> ppvStackFrame = (void **) ptContext->uc_mcontext.jmp_context.gpr[1];
> do
> {
> sprintf(sString, "(%2d) 0x%p\n", iFrame, pvInstructionPointer);
> write(iFd, sString, strlen(sString));
>
> /* Have we hit the bottom of the stack? */
> if (!ppvStackFrame[0])
> break;
>
> /* Validate the stack frame before using any portion of it */
> if (!ValidAddress((void *) ppvStackFrame) ||
> !ValidAddress((void *) ppvStackFrame[0]) ||
> !ValidAddress((void *) ((void **) ppvStackFrame[0] + 2)))
> {
> sprintf(sString, "Invalid frame at %p\n", (void *) ppvStackFrame);
> write(iFd, sString, strlen(sString));
> break;
> }
>
> ppvStackFrame = (void **) ppvStackFrame[0];
> pvInstructionPointer = ppvStackFrame[2];
> iFrame++;
> } while(ppvStackFrame);
>
> Cheers,
> Shaun
>
>



thanks Shaun for the code fragment. I'm using it in conjuction
with the GNU "bfd" library to do what I want. If anyone else
is interested, you can use the code fragment above with code
fragments from GNU binutils as a solution (look at say,
addr2line.c)

I'm sure there is a more streamlined way to do this but this is
a good starting point.

adrian


Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 03:41 PM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com