> On architectures that don't push the return address on the 
> stack during the call instruction, the caller of getcallerpc
> will have saved the desired return address somewhere in
> its stack frame, and getcallerpc must root it out.

It appears the implementation below
works well with arm-elf-gcc on arm7tdmi:

        /*
         * Functions generated by arm-elf-gcc start
         * like this (always?):
         *      mov     ip, sp
         *      stmdb   sp!, {fp, ip, lr, pc}
         *
         * (The first argument, which is still in r0,
         * is pushed later, when its address is taken so
         * that it can be provided to getcallerpc.)
         *
         * To get the value of `lr', the return address,
         * walk up the stack, starting with x, until a
         * value *u is found which is the previous stack
         * pointer, i.e. which equals the address u+3.
         * In that case, the return address is expected
         * to be in u[1].
         *
         * If no such address is found, return an invalid value.
         */
        ulong
        getcallerpc(void *x)
        {
                ulong *u;
                int     i;
        
                u = (ulong*)x;
                for (i=0; i<128; i++, u++)
                        if (*u == (ulong)(u+3))
                                return u[1];
                return ~0;
        }

A helpful document was http://www.cems.uwe.ac.uk/~cduffy/es/5.ppt,
to get an idea of how function arguments are provided
and the stack is managed by the gcc on arm.

If the stack contains a value which matches the
condition for `ip', but which is not ip, getcallerpc
will find it before the real ip/lr, and report a
garbage address.

Michael


Reply via email to