Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Mar 2004 12:20:36 -0800
From:      Peter Wemm <peter@wemm.org>
To:        amd64@freebsd.org
Subject:   Heads up.. bug fix in the pipeline...
Message-ID:  <200403201220.36148.peter@wemm.org>

next in thread | raw e-mail | index | archive | help

--Boundary-00=_UeKXAY7r8NP41z7
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

I have a pending commit that is going to cause quite a bit of impact..

The problem is that several bugs in the stack alignment code have 
conspired to cause subtle explosions at hard-to-track times.  I'm 
pretty sure these are the cause of the ogg123 crashes, for example.

Here's what was wrong..
1) the /usr/lib/crti.o and crtn.o files did not have the correct stack 
alignment conventions.
2) ld-elf.so.1 called its startup routine (_rtld()) with the wrong stack 
alignment.  Since _rtld() loads the libraries and calls their _init 
functions (which come from crti/crtn.o), the two wrongs made a right 
and the constructors were accidently called with the right alignment. 
3) _rtld_bind() in ld-elf.so.1 was called with the wrong alignment.  It 
has callbacks into libpthread for the locking.  Depending on kse thread 
state, it could blow up.  I think this was the specific cause of the 
ogg123 bug.
4) dlopen() and dlclose() were called with the right alignment, but 
since _init/_fini() were wrong, any constructors called from there 
would be called with the wrong alignment.  Even if it was the same 
libraries that worked by accident in 2) above.
5) _fini() was always called with the wrong alignment.

The good news is that the fixes are small.  The bad news is that 
crti/crtn.o are linked into *every single shared library!*.  Any 
libraries that contain C++ code and use static constructors will need 
to be recompiled after ld-elf.so.1 is fixed (since one of the 
double-wrongs in 2) wll be corrected, leaving a single wrong).

So. that means that the fix will make some things magically start 
working after a 'make world'.  And it might break a few things from 
ports.  A recompile (portupgrade -f) should fix it.

I don't know of a good way to detect shared libraries that have static 
constructors or not.  But it shouldn't be hard to decode objdump etc.

Anyway, I'm planning to commit these fixes soon, after I've finished 
testing to make sure that nothing new breaks.

FYI, the change so far is attached..

-- 
Peter Wemm - peter@wemm.org; peter@FreeBSD.org; peter@yahoo-inc.com
"All of this is for nothing if we don't go to the stars" - JMS/B5

--Boundary-00=_UeKXAY7r8NP41z7
Content-Type: text/x-diff;
  charset="us-ascii";
  name="hammer.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="hammer.diff"

Index: lib/csu/amd64/crti.S
===========================================================================
--- lib/csu/amd64/crti.S	2004/03/20 12:10:39	#1
+++ lib/csu/amd64/crti.S	2004/03/20 12:10:39
@@ -28,12 +28,14 @@
 	.globl	_init
 	.type	_init,@function
 _init:
+	subq	$8,%rsp
 
 	.section .fini,"ax",@progbits
 	.align	4
 	.globl	_fini
 	.type	_fini,@function
 _fini:
+	subq	$8,%rsp
 
 	.section .rodata
 .ascii "$FreeBSD: src/lib/csu/amd64/crti.S,v 1.6 2002/05/15 04:19:49 obrien Exp $\0"
Index: lib/csu/amd64/crtn.S
===========================================================================
--- lib/csu/amd64/crtn.S	2004/03/20 12:10:39	#1
+++ lib/csu/amd64/crtn.S	2004/03/20 12:10:39
@@ -24,9 +24,11 @@
  */
 
 	.section .init,"ax",@progbits
+	addq	$8,%rsp
 	ret
 
 	.section .fini,"ax",@progbits
+	addq	$8,%rsp
 	ret
 
 	.section .rodata
Index: libexec/rtld-elf/amd64/rtld_start.S
===========================================================================
--- libexec/rtld-elf/amd64/rtld_start.S	2004/03/20 12:10:39	#2
+++ libexec/rtld-elf/amd64/rtld_start.S	2004/03/20 12:10:39
@@ -31,14 +31,13 @@
 	.type	.rtld_start,@function
 .rtld_start:
 	xorq	%rbp,%rbp		# Clear frame pointer for good form
-	subq	$16,%rsp		# A place to store exit procedure addr
+	subq	$24,%rsp		# A place to store exit procedure addr
 	movq	%rdi,%r12
 	movq	%rsp,%rsi		# save address of exit proc
 	movq	%rsp,%rdx		# construct address of obj_main
 	addq	$8,%rdx
 	call	_rtld@PLT		# Call rtld(sp); returns entry point
 	popq	%rsi			# Get exit procedure address
-	addq	$8,%rsp			# Ignore obj_main
 	movq	%r12,%rdi		# *ap
 /*
  * At this point, %rax contains the entry point of the main program, and
@@ -62,8 +61,9 @@
  * assembly-language code that is not ABI-compliant.
  *
  * Stack map:
- * reloff       0x58
- * obj          0x50
+ * reloff       0x60
+ * obj          0x58
+ * spare	0x50
  * rflags       0x48
  * rax          0x40
  * rdx          0x38
@@ -79,6 +79,7 @@
 	.globl	_rtld_bind_start
 	.type	_rtld_bind_start,@function
 _rtld_bind_start:
+	subq	$8,%rsp
 	pushfq				# Save rflags
 	pushq	%rax			# Save %rax
 	pushq	%rdx			# Save %rdx
@@ -90,15 +91,15 @@
 	pushq	%r10			# Save %r10
 	pushq	%r11			# Save %r11
 
-	movq	0x50(%rsp),%rdi		# Fetch obj argument
-	movq	0x58(%rsp),%rsi		# Fetch reloff argument
+	movq	0x58(%rsp),%rdi		# Fetch obj argument
+	movq	0x60(%rsp),%rsi		# Fetch reloff argument
 	leaq	(%rsi,%rsi,2),%rsi	# multiply by 3
 	leaq	(,%rsi,8),%rsi		# now 8, for 24 (sizeof Elf_Rela)
 
 	call	_rtld_bind@PLT		# Transfer control to the binder
 	/* Now %rax contains the entry point of the function being called. */
 
-	movq	%rax,0x58(%rsp)		# Store target over reloff argument
+	movq	%rax,0x60(%rsp)		# Store target over reloff argument
 	popq	%r11			# Restore %r11
 	popq	%r10			# Restore %r10
 	popq	%r9			# Restore %r9
@@ -109,5 +110,5 @@
 	popq	%rdx			# Restore %rdx
 	popq	%rax			# Restore %rax
 	popfq				# Restore rflags
-	leaq	8(%rsp),%rsp		# Discard obj, do not change rflags
+	leaq	16(%rsp),%rsp		# Discard spare, obj, do not change rflags
 	ret				# "Return" to target address

--Boundary-00=_UeKXAY7r8NP41z7--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200403201220.36148.peter>