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 ...
| |||||||
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| 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 |
| |||
| 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. |
| |||
| 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! |
| |||
| "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 |
| |||
| "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 |
| |||
| "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 |
| ||||
| 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 |