9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] getcallerpc on arm7
@ 2008-03-27 10:25 Michael Teichgräber
  2008-03-31 16:24 ` Russ Cox
  0 siblings, 1 reply; 5+ messages in thread
From: Michael Teichgräber @ 2008-03-27 10:25 UTC (permalink / raw)
  To: 9fans

Hi,

trying to adapt the getcallerpc function - that
exists on Plan9 and p9p - to the arm7 using the arm-elf-gcc
compiler, I realized that this would not be easy, as
most function arguments are put into registers
(the return value into lr), and only pushed on the
stack on demand - so it seems one can not expect to find
the return address at a fixed position starting with
the first argument's address.

(Looking at runtime some ulongs around &firstarg I
actually can see the return address, but it is a varying
number of longs upwards (not downwards) of &firstarg)

I wonder under what conditions plan9port's
"return ((ulong*)x)[-2]" for arm-linux/gcc actually works.

So far I found out that I could implement getcallerpc as
a macro using gcc's __builtin_return_address(0), but this would
not fit getcallerpc's normal behaviour (which I suppose
only depends on &firstarg, not the current function
context).

Although I know that the Plan9 compilers and gcc organize
function calls differently, I thought it would be helpful to
understand what /sys/src/libc/arm/getcallerpc.s does -
after having a look at A Manual for the Plan 9 assembler:

	MOVW	0(R13), R0
	RET

Does this mean that it is just returning the contents of the
first word on the Stack (R13) - and not interpreting &firstarg
at all?

Thanks for any hint,

Michael


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [9fans] getcallerpc on arm7
  2008-03-27 10:25 [9fans] getcallerpc on arm7 Michael Teichgräber
@ 2008-03-31 16:24 ` Russ Cox
  2008-03-31 17:23   ` Michael Teichgräber
  2008-03-31 19:09   ` Charles Forsyth
  0 siblings, 2 replies; 5+ messages in thread
From: Russ Cox @ 2008-03-31 16:24 UTC (permalink / raw)
  To: 9fans

> Although I know that the Plan9 compilers and gcc organize
> function calls differently, I thought it would be helpful to
> understand what /sys/src/libc/arm/getcallerpc.s does -
> after having a look at A Manual for the Plan 9 assembler:
>
> 	MOVW	0(R13), R0
> 	RET
>
> Does this mean that it is just returning the contents of the
> first word on the Stack (R13) - and not interpreting &firstarg
> at all?

This appears to be wrong, but I don't have time to dig in.

The pointer is intended to be used on architectures like the x86
that automatically push the return address on the stack.

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.

vc (the MIPS compiler) saves the return PC in the very last
word of the stack frame, so that /sys/src/libc/mips/getcallerpc.s:

	TEXT	getcallerpc(SB), $0
		MOVW	0(SP), R1
		RET

is correct.

It appears that 5c (the ARM compiler) saves the return PC
as the first word of the stack frame, which may be somewhat
hard to locate.

Russ



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [9fans] getcallerpc on arm7
  2008-03-31 16:24 ` Russ Cox
@ 2008-03-31 17:23   ` Michael Teichgräber
  2008-03-31 19:09   ` Charles Forsyth
  1 sibling, 0 replies; 5+ messages in thread
From: Michael Teichgräber @ 2008-03-31 17:23 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

> 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



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [9fans] getcallerpc on arm7
  2008-03-31 16:24 ` Russ Cox
  2008-03-31 17:23   ` Michael Teichgräber
@ 2008-03-31 19:09   ` Charles Forsyth
  2008-03-31 22:34     ` Michael Teichgräber
  1 sibling, 1 reply; 5+ messages in thread
From: Charles Forsyth @ 2008-03-31 19:09 UTC (permalink / raw)
  To: 9fans

>It appears that 5c (the ARM compiler) saves the return PC
>as the first word of the stack frame, which may be somewhat
>hard to locate.

it should be the same as the other risc machines, and seems
all right when i test it with 5c/5l.  gcc typically also uses a frame
pointer, which might make it nearly as easy for that compiler.



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [9fans] getcallerpc on arm7
  2008-03-31 19:09   ` Charles Forsyth
@ 2008-03-31 22:34     ` Michael Teichgräber
  0 siblings, 0 replies; 5+ messages in thread
From: Michael Teichgräber @ 2008-03-31 22:34 UTC (permalink / raw)
  To: Fans of the OS Plan 9 from Bell Labs

> it should be the same as the other risc machines, and seems all right
> when i test it with 5c/5l.  gcc typically also uses a frame pointer,
> which might make it nearly as easy for that compiler.

This seems to work well:

	.text
	.globl getcallerpc
	getcallerpc:
		ldr	r0, [fp, #-4]
		bx	lr

I was a bit confused about whether or not the firstarg pointer
is expected to be used by a getcallerpc implementation (so that
it would also work in subfunctions of the current, provided
&firstarg is passed down). The BUGS section of getcallerpc(2/3)
gives a hint how this could be answered.


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-03-31 22:34 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-27 10:25 [9fans] getcallerpc on arm7 Michael Teichgräber
2008-03-31 16:24 ` Russ Cox
2008-03-31 17:23   ` Michael Teichgräber
2008-03-31 19:09   ` Charles Forsyth
2008-03-31 22:34     ` Michael Teichgräber

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).