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

Stack Trace of current stack?

3,418 views
Skip to first unread message

Bob Bradley

unread,
Oct 1, 2002, 6:31:48 AM10/1/02
to
Is there an easy way to get a stack trace of the current stack? tt() and
the code from the VxWorks FAQ work except when called on the current
task.

I'd like to add an option to my debugging asserts to provide a stack
trace (e.g. when a bad parameter is detected, I can more easily see who
passed it).

Rather than manually parse the stack frame, I figured I could send the
current task ID to a message queue and wait on a reply then have a debug
task receive the message, do a tt() or trcStack() on that task ID, and
reply, but I was hoping for a little cleaner solution.

agree.with.these.terms@mail.zevenaar.org Renee Teunissen

unread,
Oct 1, 2002, 7:45:50 AM10/1/02
to
Take a look at this wonderfull FAQ:
http://www.xs4all.nl/~borkhuis/vxworks/vxw_pt5.html
search for "trcStack"

Greetz,
Renee.
------------------------
Renee Teunissen
PTS Software bv

------------------------
Q: How can I build a stack-trace?

A: You can do this using an undocumented function called "trcStack".
Here is all you need. You can even call xxxTrace(tid) from interrupt
level... though logMsg() is far from ideal.

/*********************************************************************
**********
*
* xxxTracePrint - stack trace print function
*
* RETURNS: OK or ERROR
*/

static void xxxTracePrint
(
INSTR *caller,
int func,
int nargs,
int *args
)
{
char buf [250];
int ix;
int len = 0;

len += sprintf (&buf [len], "%#10x: %#10x (", (int)caller, func);
for (ix = 0; ix < nargs; ix++)
{
if (ix != 0)
len += sprintf (&buf [len], ", ");
len += sprintf (&buf [len], "%#x", args [ix]);
}

len += sprintf (&buf [len], ")\n");

logMsg (buf);
}

/*********************************************************************
**********
*
* xxxTrace - stack trace
*
* RETURNS: OK or ERROR
*/

int xxxTrace
(
WIND_TCB *pTcb
)
{
REG_SET regs;

if (pTcb == NULL)
return (ERROR);

taskRegsGet ((int)pTcb, &regs);
trcStack (&regs, (FUNCPTR) xxxTracePrint, (int)pTcb);

return (OK);
}

(From: Geoffrey Espin, es...@idiom.com)

Bob Bradley

unread,
Oct 1, 2002, 4:52:48 PM10/1/02
to
In article <10334799...@newsreader2.wirehub.nl>,
"Renee Teunissen"
<if.you.spam.me.I.will.charge.you.1000.Euro.By.emailing.me.you
agree.with....@mail.zevenaar.org> wrote:

> Take a look at this wonderfull FAQ:
> http://www.xs4all.nl/~borkhuis/vxworks/vxw_pt5.html
> search for "trcStack"

I am trying to get a stack trace of the current stack, which is not
supported by the code from the FAQ (or tt()). trcStack() in general
doesn't appear to support getting a stack trace of the current stack.

John

unread,
Oct 2, 2002, 1:05:00 AM10/2/02
to
Hello,

This may, or may not work... worth a try though:

void traceMe (void)
{
REG_SET regs;

taskDelay (1); /* Force context save */

taskRegsGet (0, &regs);

trcStack (&regs,
NULL, /* NULL for default print routine */
0); /* 0 for myself */

}


The context save should get an approximately correct set of registers
into the TCB. The only thing I can see causing a problem here is the
heuristic scanner code that tries to determine where in the life of a
function the PC is (i.e. is the PC in the prologue, the main function
code or the epilogue).

Try it and post the results, either way, so that others can benefit
from your findings in the future. Make sure you tell us the
architecture you tried too...

HTH,

John...

Bob Bradley <b...@chaoticsoftware.com> wrote in message news:<bob-841AE1.1...@news.apple.com>...

agree.with.these.terms@mail.zevenaar.org Renee Teunissen

unread,
Oct 2, 2002, 3:15:00 AM10/2/02
to
It does work, btw - I could trace the stack of the shell I was working
on :)

But stacktracing of the currect task is an illusion, think about it.
The stack should - if correct - always end in trcStack or one of it's
sibblings or... not ;) Please rethink your problem..

Otherwise, you could just grep the registers and task info, and trace
the framepointer until you are at the end, and start with the current
framepointer (see your regs). This should not be so difficult. The
framepoint can easily be found on a fixed offset of the stackpointer.
Every local stack frame has a pointer to the previous stack frame and
so on. This is - so far I can see from here - the samething trcStack
does. Therefore it needs the regs. So if oyu manually fill-in the
framepointer of a regs-struct you could nice things with it ;) All
function arguments are on a standard offset of the
framepointer/stackpointer.

Btw, you didnt compile the thing with the omit-framepointer (or
something like that) option - did you?


"Bob Bradley" <b...@chaoticsoftware.com> wrote in message
news:bob-841AE1.1...@news.apple.com...

Bob Bradley

unread,
Oct 2, 2002, 3:36:55 AM10/2/02
to
In article <10335429...@newsreader1.wirehub.nl>,

"Renee Teunissen"
<if.you.spam.me.I.will.charge.you.1000.Euro.By.emailing.me.you
agree.with....@mail.zevenaar.org> wrote:

> It does work, btw - I could trace the stack of the shell I was working
> on :)

When I try to use either tt() or trcStack() on the current task, it just
prints an error that it cannot run trace the curret stack. The
documentation for tt() describes this as a limitation as well.

> But stacktracing of the currect task is an illusion, think about it.
> The stack should - if correct - always end in trcStack or one of it's
> sibblings or... not ;) Please rethink your problem..

It's okay if it ends in trcStack because I would still be able to see
how it got there. For example, if a() calls b(), b() calls c(), and c()
calls trcStack, I would be able to see:

trcStack
c
b
a

agree.with.these.terms@mail.zevenaar.org Renee Teunissen

unread,
Oct 2, 2002, 7:40:27 AM10/2/02
to
I see...
What I would do then...

get your currect framepointer.

look: (pentium based target)

-> ti tPortmapd

NAME ENTRY TID PRI STATUS PC SP
ERRNO DELAY
---------- ------------ -------- --- ---------- -------- -------- ----
--- -----
tPortmapd _portmapd 3dc47dc 100 PEND 11a5b4 3dc46ac
16 0

stack: base 0x3dc47dc end 0x3dc3454 size 4988 high 528 margin
4460

options: 0x7
VX_SUPERVISOR_MODE VX_UNBREAKABLE VX_DEALLOC_STACK

edi = 3dc47dc esi = 0 ebp = 3dc4744 esp =
3dc46ac
ebx = 3dc4714 edx = 0 ecx = 0 eax =
0
eflags = 246 pc = 11a5b4
value = 0 = 0x0

The framepointer (ebp) = 0x3dc4744

-> d 0x3dc4744
03dc4740: 478c 03dc 56e9 001a 0100 0000 *
G...V......*
03dc4750: 476c 03dc 0000 0000 0000 0000 0000 0000
*lG..............*
03dc4760: ec74 03e7 479c 03dc 0000 0000 0000 0000
*t....G..........*
03dc4770: 0000 0000 0000 0000 0000 0000 0000 0000
*................*
03dc4780: 0000 0000 0000 0000 0000 0000 47ac 03dc
*.............G..*
03dc4790: d963 0018 0000 0000 0000 0000 02ee 6f00
*c..............o*
03dc47a0: 0000 0000 eeee eeee 0530 0013 0000 0000
*........0.......*
03dc47b0: 053c 0013 0000 0000 0000 0000 0000 0000
*<...............*
03dc47c0: 0000 0000 0000 0000 0000 0000 0000 0000
*................*
03dc47d0: 0000 0000 0000 0000 0000 0000 0000 0000
*................*
03dc47e0: 0000 0000 0064 0000 47e8 c3dc 47e8 c3dc
*....d....G...G..*
03dc47f0: 47f0 c3dc 47f0 c3dc 47f8 c3dc 32bc 03dc
*.G...G...G...2..*
03dc4800: 1bf0 03e1 4800 c3dc 4808 c3dc a12c 001b
*.....H...H..,...*
03dc4810: 3454 03dc 0007 0000 0002 0000 0064 0000
*T4..........d...*
03dc4820: 0064 0000 0000 0000 0000 0000 0000 0000
*d...............*
03dc4830: 0000 0000 0000 0000 4874 03dc 0000 0000
*........tH......*
03dc4840: 0000 0000
*................*
value = 21 = 0x15

at that address you'll find the address of the next framepointer and
on that address the next one until you'll find 0

here you find:
ebp = 03dc.4744 -> 03dc.478c -> 03dc.47ac -> 0000.0000

the integer after that you'll find the return adres, which is the code
space of the calling program. thus begin of function + offset.

ebp = 03dc.4744, on 03dc.474c you'll find: 001a.56e9

so the call three is:
this func is called from 001a.56e9 is called from 0018.d963 called
from 0013053c

if you apply: tCh_symName on 001a.56e9 you will get the symbol name +
offset (diff contans this offset)

put this is a function and...

Please post your findings and code - if possible.


also see:
http://packetstormsecurity.nl/docs/infosec/buffer-overflows/random-sta
ck.text which describes those nasty stackoverun exploids. Those docs
are a prefect illustration how the stack works and how to use it for
you own bennefits, which is in our case, stack tracing. You'll find
more interesting docs on packetstorm with respect to stack and heap
memory issues.

-------------------
LOCAL STATUS
tCh_symName(void* addr, char* symName, int* diff)
{
SYM_TYPE t;
int val;
char buf[512];

if( symFindByValue(sysSymTbl, (int)addr, buf, &val, &t) == OK)
{
if( diff != NULL ) {
*diff = (int) addr - val;

if( *diff == 0)
{
sprintf(symName, "%#10x %16.16s", val, buf);
} else
{
sprintf(symName, "%#10x %16.16s + 0x%x", val, buf, *diff);
}
return OK;
}
else {
if( (int)addr != val)
{
sprintf(symName, "_0x%x", addr);
return ERROR;
}
else {
sprintf(symName, "%#10x %16.16s", val, buf);
return OK;
}
}
}

sprintf(symName, "_0x%x", addr);

return ERROR;
}

-------------------

"Bob Bradley" <b...@chaoticsoftware.com> wrote in message

news:bob-0EE16C.0...@news.apple.com...

David Laight

unread,
Oct 2, 2002, 10:14:53 AM10/2/02
to
Renee Teunissen wrote:
> I see...
> What I would do then...
>
> get your currect framepointer.

<enourmous snip>

Yes - for some reason the tt function doesn't use the frame pointer,
instead it (tries to) parse the instructions to find an exit path
from each routine and hence the return address.

Worse still, it does this recursively and only prints anything
once it has found the stack base. This is done solely to
reverse the order of the printout - which is completely unnecessary.

If (ie when) it fails to find the stack base (eg anything called
as a native method from pjava on a strongarm) you get no info at
all.....

If you have stack frames then they can be used to trivially
generate a backtrace.

Actually I wonder if it possible to patch out the check that
stops tt() working on the current process?
I didn't ever try.

David

agree.with.these.terms@mail.zevenaar.org Renee Teunissen

unread,
Oct 2, 2002, 10:45:37 AM10/2/02
to

"David Laight" <da...@spam.me.l8s.co.uk> wrote in message
news:anev0s$dak$1...@helle.btinternet.com...

> Renee Teunissen wrote:
> > I see...
> Yes - for some reason the tt function doesn't use the frame pointer,
> instead it (tries to) parse the instructions to find an exit path
> from each routine and hence the return address.

I never analysed what tt() does, just tried to find an answer :)

this should work on INTEL:
---------------------------------------------
int
tCh_Trace(unsigned int ebp)
{
unsigned int *fbptr;
unsigned int *retad;

fbptr = (unsigned int *)ebp;
retad = fbptr+1;
do
{
printf("fbptr : %p: %8.8x\n", fbptr, *fbptr);
printf("retaddress : %8.8x\n", *retad);
printf("---------------\n");

fbptr = (unsigned int *) *fbptr;
retad = fbptr+1;
} while( fbptr );

return 0;
}
---------------------------------------------

just call it with the ebp you get from taskRegsGet or using another
method :)

>
> Worse still, it does this recursively and only prints anything
> once it has found the stack base. This is done solely to
> reverse the order of the printout - which is completely unnecessary.

I agree. Thou tt() displays info which cant be found otherwise, i
guess.. like the callee's address.
I thought I should find a 'call <address>' intruction at (*retad)-1 or
something like that and then I found out there is an CALL EAX :(
(I'm not that deep in asembler)

> If (ie when) it fails to find the stack base (eg anything called
> as a native method from pjava on a strongarm) you get no info at
> all.....

I know..


> If you have stack frames then they can be used to trivially
> generate a backtrace.
>
> Actually I wonder if it possible to patch out the check that
> stops tt() working on the current process?
> I didn't ever try.

call trcStack you current process and see what happens ;)
put the code in johan borkhuis FAQ in to a file and compile it, you'll
see what happens...
(my expiriences differ from a endless loop until a reboot)


The routine above can be extented to find much more. dont have time to
do that, this should give a smart guy/girl enought idears... as we all
known from our college textbooks "... is left as an exercise to the
reader" ;)

And read those hacking dox at packetstormsecurity.org, they'll provide
at lot of info to geet some real debugging expirience :)


Cheers,
Renee
- - - - - - - -
Renee A. Teunissen
PTS Software bv, Meerweg 7, 1405BA Bussum, NL.
T.+31-(0)35-6926969, M.+31-(0)6-22778313,
http://www.pts.nl, <first_name>@pts.nl
personal link page: http://wittenburg10c.nl/db/dest/links.html

0 new messages