[klibc] [PATCH v2] Fix sparc assembly when compiled as PIC

James Clarke
Wed, 18 Jul 2018 22:11:08 -0000

Some distributions default to PIE for their compilers, which on sparc is passed
on to the assembler. Since the behaviour of %hi/%lo changes under PIC to become
GOT offsets, the current assembly files need adapting to not try to use a GOT
offset as an absolute address.
---
Changes since v1:

  * Don't put the start of PIC_PROLOGUE in the delay slot of the branch
    after the pipe syscall, since that clobbers %g4 which is used as a
    saved register on the success path.

 usr/include/arch/sparc/machine/asm.h     | 15 +++++++++++++--
 usr/include/arch/sparc64/machine/asm.h   |  1 +
 usr/include/arch/sparc64/machine/frame.h |  1 +
 usr/klibc/arch/sparc/pipe.S              |  5 +++--
 usr/klibc/arch/sparc/syscall.S           |  6 ++++--
 usr/klibc/arch/sparc/sysfork.S           |  6 ++++--
 usr/klibc/arch/sparc64/pipe.S            |  5 +++--
 usr/klibc/arch/sparc64/syscall.S         |  6 ++++--
 usr/klibc/arch/sparc64/sysfork.S         |  6 ++++--
 9 files changed, 37 insertions(+), 14 deletions(-)

diff --git a/usr/include/arch/sparc/machine/asm.h
b/usr/include/arch/sparc/machine/asm.h
index 04fe9b1b..fd9ef1ef 100644
--- a/usr/include/arch/sparc/machine/asm.h
+++ b/usr/include/arch/sparc/machine/asm.h
@@ -61,7 +61,7 @@
 #endif
 #define	_ASM_LABEL(name)	name

-#ifdef PIC
+#ifdef __PIC__
 /*
  * PIC_PROLOGUE() is akin to the compiler generated function prologue for
  * PIC code. It leaves the address of the Global Offset Table in DEST,
@@ -83,12 +83,20 @@
 0: \
 	add dest,%o7,dest; \
 	mov tmp, %o7
+#define SET(var,base,dest) \
+	sethi %gdop_hix22(var), dest; \
+	xor dest, %gdop_lox10(var), dest; \
+	ldx [base + dest], dest, %gdop(var)
 #else
 #define PIC_PROLOGUE(dest,tmp) \
 	mov %o7,tmp; 3: call 4f; nop; 4: \
 	sethi %hi(_C_LABEL(_GLOBAL_OFFSET_TABLE_)-(3b-.)),dest; \
 	or dest,%lo(_C_LABEL(_GLOBAL_OFFSET_TABLE_)-(3b-.)),dest; \
 	add dest,%o7,dest; mov tmp,%o7
+#define SET(var,base,dest) \
+	sethi %gdop_hix22(var), dest; \
+	xor dest, %gdop_lox10(var), dest; \
+	ld [base + dest], dest, %gdop(var)
 #endif

 /*
@@ -106,7 +114,10 @@
 #endif
 #else
 #define PIC_PROLOGUE(dest,tmp)
-#define PICCY_OFFSET(var,dest,tmp)
+#define SET(var,base,dest) \
+	sethi %hi(var), dest; \
+	or dest, %lo(var), dest
+#define PICCY_SET(var,dest,tmp) SET(var,tmp,dest)
 #endif

 #define FTYPE(x)		.type x, at function
diff --git a/usr/include/arch/sparc64/machine/asm.h
b/usr/include/arch/sparc64/machine/asm.h
new file mode 100644
index 00000000..394ba865
--- /dev/null
+++ b/usr/include/arch/sparc64/machine/asm.h
@@ -0,0 +1 @@
+#include "../../sparc/machine/asm.h"
diff --git a/usr/include/arch/sparc64/machine/frame.h
b/usr/include/arch/sparc64/machine/frame.h
new file mode 100644
index 00000000..79beea6d
--- /dev/null
+++ b/usr/include/arch/sparc64/machine/frame.h
@@ -0,0 +1 @@
+#include "../../sparc/machine/frame.h"
diff --git a/usr/klibc/arch/sparc/pipe.S b/usr/klibc/arch/sparc/pipe.S
index a8abf3c3..e278bda5 100644
--- a/usr/klibc/arch/sparc/pipe.S
+++ b/usr/klibc/arch/sparc/pipe.S
@@ -5,6 +5,7 @@
  * they return the two file descriptors in %o0 and %o1.
  */

+#include <machine/asm.h>
 #include <asm/unistd.h>

 	.globl	pipe
@@ -16,8 +17,8 @@ pipe:
 	t	0x10
 	bcc	1f
 	  nop
-	sethi	%hi(errno), %g4
-	or	%g4, %lo(errno), %g4
+	PIC_PROLOGUE(%g1,%g4)
+	SET(errno,%g1,%g4)
 	st	%o0,[%g4]
 	retl
 	  mov	-1, %o0
diff --git a/usr/klibc/arch/sparc/syscall.S b/usr/klibc/arch/sparc/syscall.S
index c0273f77..52a8583b 100644
--- a/usr/klibc/arch/sparc/syscall.S
+++ b/usr/klibc/arch/sparc/syscall.S
@@ -4,14 +4,16 @@
  * Common system-call stub; %g1 already set to syscall number
  */

+#include <machine/asm.h>
+
 	.globl	__syscall_common
 	.type	__syscall_common,#function
        	.align	4
 __syscall_common:
 	t	0x10
 	bcc	1f
-	  sethi	%hi(errno), %g4
-	or	%g4, %lo(errno), %g4
+	  PIC_PROLOGUE(%g1,%g4)
+	SET(errno,%g1,%g4)
 	st	%o0,[%g4]
 	mov	-1, %o0
 1:
diff --git a/usr/klibc/arch/sparc/sysfork.S b/usr/klibc/arch/sparc/sysfork.S
index a66c76e9..3787b944 100644
--- a/usr/klibc/arch/sparc/sysfork.S
+++ b/usr/klibc/arch/sparc/sysfork.S
@@ -8,6 +8,8 @@
  * Common system-call stub; %g1 already set to syscall number
  */

+#include <machine/asm.h>
+
 	.globl	__syscall_forkish
 	.type	__syscall_forkish,#function
        	.align	4
@@ -16,8 +18,8 @@ __syscall_forkish:
 	sub	%o1, 1, %o1
 	bcc,a	1f
 	  and	%o0, %o1, %o0
-	sethi	%hi(errno), %g4
-	or	%g4, %lo(errno), %g4
+	PIC_PROLOGUE(%g1,%g4)
+	SET(errno,%g1,%g4)
 	st	%o0,[%g4]
 	mov	-1, %o0
 1:
diff --git a/usr/klibc/arch/sparc64/pipe.S b/usr/klibc/arch/sparc64/pipe.S
index c63b20f7..cb5c2c79 100644
--- a/usr/klibc/arch/sparc64/pipe.S
+++ b/usr/klibc/arch/sparc64/pipe.S
@@ -5,6 +5,7 @@
  * they return the two file descriptors in %o0 and %o1.
  */

+#include <machine/asm.h>
 #include <asm/unistd.h>

 	.globl	pipe
@@ -16,8 +17,8 @@ pipe:
 	t	0x6d
 	bcc	%xcc, 1f
 	  nop
-	sethi	%hi(errno), %g4
-	or	%g4, %lo(errno), %g4
+	PIC_PROLOGUE(%g1,%g4)
+	SET(errno,%g1,%g4)
 	st	%o0,[%g4]
 	retl
 	  mov	-1, %o0
diff --git a/usr/klibc/arch/sparc64/syscall.S b/usr/klibc/arch/sparc64/syscall.S
index 7ab9d95f..c84c9ae5 100644
--- a/usr/klibc/arch/sparc64/syscall.S
+++ b/usr/klibc/arch/sparc64/syscall.S
@@ -4,14 +4,16 @@
  * Common system-call stub; %g1 already set to syscall number
  */

+#include <machine/asm.h>
+
 	.globl	__syscall_common
 	.type	__syscall_common,#function
        	.align	4
 __syscall_common:
 	t	0x6d
 	bcc	%xcc, 1f
-	  sethi	%hi(errno), %g4
-	or	%g4, %lo(errno), %g4
+	  PIC_PROLOGUE(%g1,%g4)
+	SET(errno,%g1,%g4)
 	st	%o0,[%g4]
 1:
        	retl
diff --git a/usr/klibc/arch/sparc64/sysfork.S b/usr/klibc/arch/sparc64/sysfork.S
index 2eed659e..a0c13340 100644
--- a/usr/klibc/arch/sparc64/sysfork.S
+++ b/usr/klibc/arch/sparc64/sysfork.S
@@ -8,6 +8,8 @@
  * Common system-call stub; %g1 already set to syscall number
  */

+#include <machine/asm.h>
+
 	.globl	__syscall_forkish
 	.type	__syscall_forkish,#function
        	.align	4
@@ -16,8 +18,8 @@ __syscall_forkish:
 	sub	%o1, 1, %o1
 	bcc,a	%xcc, 1f
 	  and	%o0, %o1, %o0
-	sethi	%hi(errno), %g4
-	or	%g4, %lo(errno), %g4
+	PIC_PROLOGUE(%g1,%g4)
+	SET(errno,%g1,%g4)
 	st	%o0, [%g4]
 	retl
 	  mov	-1, %o0
--
2.18.0