Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20160402170228.GA3178@dora.lan>
Date: Sat, 2 Apr 2016 12:02:28 -0500
From: Bobby Bingham <koorogi@...rogi.info>
To: musl@...ts.openwall.com
Subject: Re: [PATCH 2/2] add powerpc64 port

On Sun, Mar 27, 2016 at 10:18:56PM -0400, Rich Felker wrote:
> > In the ABI, C functions have two entry points, the "global" entry point,
> > and the "local" entry point.  The local entry point expects the "table of
> > contents" pointer in r2.  The global entry point expects the address of
> > global entry point itself in r12, uses the prologue I used here to
> > calculate the TOC pointer from it, and falls through to the local entry
> > point.  See section 2.3.2.1 of the ABI spec linked above.
> > 
> > Calls within the same module are resolved to the local entry point, so
> > we need to ensure r2 is set up with the TOC pointer here to call any C
> > code.
> > 
> > The ABI spec does specify that r12 contains the address of _start,
> > specifically so this prologue can work (section 4.1.2.1).
> 
> OK. In that case the subsequent code to compute the address of
> _DYNAMIC via PC-relative addressing using the return address is
> unnecessary, though; you already have the initial PC and can just
> compute _DYNAMIC relative to it.

Ok.

> 
> Also, for dynamic-linked programs, the main program's entry point is
> reached via CRTJMP() from the dynamic linker, and your definition is
> not setting up r12. In order to meet this part of the ELF ABI it needs
> to set r12.

Good catch.

> 
> One thing that's not clear to me is whether the jumps/calls from asm,
> as you've written them, go to the local entry point or the global
> entry point of the callee. Since you're not loading r12 I assume the
> intent is to go to the local entry point, but that only works if the
> callee is hidden. Or does the PLT take care of converting that for you
> (as long as r2 is set)?

Calls that go through the PLT go to the global entry point.  Otherwise,
they go to the local entry point.

The PLT stub saves r2 to a slot in the stack from required by the ABI to
be reserved for it, loads the global entry point address to r12, and
calls it.  Calls that might go through the PLT are required to be made
with a "bl; nop" sequence, so that the linker can replace the nop with
an instruction to reload r2 from the stack where the PLT stub saved it.

> 
> One place that looks wrong to me is sigsetjmp. I would expect r2 to be
> lost/clobbered when setjmp is called, but maybe not since it looks
> like setjmp saves it in the jmp_buf, despite it not being a call-saved
> register. Is that your expectation?

r2 is call-saved when using the local entry point.  When using the global
entry point it's technically call-clobbered, but the PLT stub and linker
conspire together to save/restore it.

> > > > diff --git a/src/signal/powerpc64/sigsetjmp.s b/src/signal/powerpc64/sigsetjmp.s
> > > > new file mode 100644
> > > > index 0000000..ce59b60
> > > > --- /dev/null
> > > > +++ b/src/signal/powerpc64/sigsetjmp.s
> > > > @@ -0,0 +1,30 @@
> > > > +	.global sigsetjmp
> > > > +	.global __sigsetjmp
> > > > +	.type sigsetjmp,%function
> > > > +	.type __sigsetjmp,%function
> > > > +	.hidden ___setjmp
> > > > +sigsetjmp:
> > > > +__sigsetjmp:
> > > > +	addis 2, 12, .TOC.-__sigsetjmp@ha
> > > > +	addi  2,  2, .TOC.-__sigsetjmp@l
> > > > +	.localentry sigsetjmp,.-sigsetjmp
> > > > +	.localentry __sigsetjmp,.-__sigsetjmp
> > > 
> > > Again I don't see what the purpose of these insns is; if the resulting
> > > value is needed, are you aware of how that interacts with ___setjmp
> > > returning twice?
> > 
> > This sets up r2 with the TOC pointer, as is required by the ABI in order
> > to call setjmp's local entry point.  Since setjmp is also written in asm,
> > we could do away with this here.
> > 
> > I don't think the fact that setjmp returns twice matters for this.
> 
> When setjmp returns the second time, all registers it did not save
> have been clobbered (by arbitrary code that ran after the first return
> from setjmp). However despite not being a call-saved register
> (AFAICT), r2 is saved by setjmp, so it's probably okay.

r2 is call-saved when calling to the local entry point, so setjmp needs
to save it.

--
Bobby

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.