This is the mail archive of the
mailing list for the binutils project.
Re: secureplt breaks ld on Alpha Linux
- From: Mikulas Patocka <mpatocka at redhat dot com>
- To: Richard Henderson <rth at twiddle dot net>
- Cc: binutils at sourceware dot org, bug-binutils at gnu dot org
- Date: Sat, 30 Aug 2014 09:46:34 -0400 (EDT)
- Subject: Re: secureplt breaks ld on Alpha Linux
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot LRH dot 2 dot 02 dot 1408291448090 dot 3870 at file01 dot intranet dot prod dot int dot rdu2 dot redhat dot com> <54010C55 dot 6070605 at twiddle dot net>
On Fri, 29 Aug 2014, Richard Henderson wrote:
> On 08/29/2014 12:29 PM, Mikulas Patocka wrote:
> > I found out that the patch cc75d373fdb9668f367959f99f0b67e056a6c18a
> > (Enable secureplt by default for alpha-linux) committed to binutils git
> > breaks ld on alpha.
> > This is a minimalized testcase that shows the breakage:
> > http://people.redhat.com/~mpatocka/testcases/alpha-ld-bug/ld-bug.tar.xz
> > To reproduce the bug, run ./ld-bug.sh to perform the linking, then run the
> > resulting binary:
> > LD_PRELOAD=./libots.so ./memset
> Incidentally, you can't package your ld.so and libc.so and then use the system
> ld.so. The ld.so and libc.so used must match. That said, removing the stuff
> redundant with my system libraries I can reproduce the crash.
> > The bug happens when using the Compaq C Compiler (ccc) on Alpha Linux (it
> > can be downloaded from
> > ftp://ftp.compaq.com/pub/products/C-CXX/linux/compaq_c/ ). When using
> > optimization, Compaq C replaces a call to memset with a call to _OtsZero
> > located in libots.so. The above patch breaks ld in such a way that the
> > resulting program crashes when performing the dynamic call to _OtsZero.
> The code that ccc is generating is incorrect:
> 1c: 00 40 5b 6b jsr ra,(t12),20 <main+0x20>
> 1c: LITUSE printf+0x3
> 1c: HINT printf
> 20: 00 00 ba 27 ldah gp,0(ra)
> 20: GPDISP *ABS*+0x8
> 24: 90 01 3f 22 lda a1,400
> 28: 00 00 bd 23 lda gp,0(gp)
> 2c: 00 00 7d a7 ldq t12,0(gp)
> 2c: ELF_LITERAL _OtsZero
> 30: 00 00 1d a6 ldq a0,0(gp)
> 30: ELF_LITERAL a
> 34: 00 00 1d a4 ldq v0,0(gp)
> 34: ELF_LITERAL .data
> 38: 00 00 fe 2f unop
> 3c: 00 40 5b 6b jsr ra,(t12),40 <main+0x40>
> 3c: LITUSE _OtsZero+0x3
> 3c: HINT _OtsZero
> 40: 00 00 7d a7 ldq t12,0(gp)
> 40: ELF_LITERAL printf
> 44: 10 00 00 22 lda a0,16(v0)
> 44: LITUSE .data+0x1
> 48: 00 00 fe 2f unop
> 4c: 00 40 5b 6b jsr ra,(t12),50 <main+0x50>
> 4c: LITUSE printf+0x3
> 4c: HINT printf
> At 0x40, the compiler has failed to reload gp after the call, like it did after
> the first call to printf at 0x20.
> The Compaq compiler seems to be assuming non-standard calling conventions in
> the call to _OtsZero. If you force LD_BIND_NOW=1 so that all relocation
> happens first, the program does run correctly.
I tested the compiler and it assumes that the function _OtsZero preserves
registers v0, t0-t11, a5, s0-s5, fp, gp, f0-f30. It can only modify a0-a4,
The function _dl_runtime_resolve_old saves these registers, so it works.
The function _dl_runtime_resolve_new doesn't save all of them.
We can't save the registers in _dl_runtime_resolve_new because
_dl_runtime_resolve_new gets its parameter in t11.
The only possibility to save them is in the code at the beginning of
_PROCEDURE_LINKAGE_TABLE_ - do you think it would be possible to save the
registers on the stack here? Or, would it cause unwind problems?
> There are several ways libots could have been written to annotate the function
> for non-standard calling conventions. But Compaq probably went under before
> that bug was exposed. Assuming that one can't get the source, it may be
> possible to modify the libots.so binary so that it works with modern linkers.
> This is not a bug in ld, per se.
What exactly these anotations do? Do they turn off lazy binding?