powerpc64 rescue/rescue link failures

Dennis Ferguson <[email protected]> Sat, 10 Jan 2015 15:59:59 -0800
Newsgroups gmane.os.netbsd.ports.powerpc
Message-ID <[email protected]>
Since the January 2 fix to the powerpc64 loader to properly
complain about this the macppc64 build has been failing
while linking rescue/rescue, this way:

#      link  rescue/rescue
[...]
/build/macppc64/obj/tooldir.NetBSD-7.99.3-amd64/lib/gcc/powerpc64--netbsd/4.8.4/../../../../powerpc64--netbsd/bin/ld: /build/macppc64/obj/destdir.macppc/usr/lib/libc.a(writev.o): In function `._sys_writev':
(.text+0xc): call to `.__cerror' lacks nop, can't restore toc; (-mcmodel=small toc adjust stub)/build/macppc64/obj/tooldir.NetBSD-7.99.3-amd64/lib/gcc/powerpc64--netbsd/4.8.4/../../../../powerpc64--netbsd/bin/ld: final link failed: Bad value

The problem is with the tail call to __cerror() which each
system call stub does (despite what the error message says).

I can fix this by brute force with the attached patch, which
inlines __cerror() everywhere it is used, but I was wondering
if there was a better way.  I see .hidden sometimes being used
for this but I have no idea if, or how, that might help this
case.

Dennis Ferguson
SYS.h.patch (application/octet-stream, 1.7 KB)
Index: lib/libc/arch/powerpc64/SYS.h
===================================================================
RCS file: /cvsroot/src/lib/libc/arch/powerpc64/SYS.h,v
retrieving revision 1.3
diff -u -r1.3 SYS.h
--- lib/libc/arch/powerpc64/SYS.h	23 Aug 2014 02:24:22 -0000	1.3
+++ lib/libc/arch/powerpc64/SYS.h	10 Jan 2015 23:16:08 -0000
@@ -3,11 +3,34 @@
 #include <machine/asm.h>
 #include <sys/syscall.h>
 
-#ifdef _CALL_AIX
-#define	BRANCH_TO_CERROR()	b	._C_LABEL(__cerror); nop
-#else
-#define	BRANCH_TO_CERROR()	b	_C_LABEL(__cerror)
-#endif
+#ifdef _REENTRANT
+#define DO_CERROR()		mflr	%r0				;\
+				streg	%r0,__SIZEOF_POINTER__(%r1)	;\
+				stptru	%r1,-(4*__SIZEOF_POINTER__)(%r1);\
+				streg	%r31,(3*__SIZEOF_POINTER__)(%r1);\
+				mr	%r31,%r3			;\
+				bl	PIC_PLT(_C_LABEL(__errno))	;\
+				nop					;\
+				stint	%r31,0(%r3)			;\
+				ldreg	%r31,(3*__SIZEOF_POINTER__)(%r1);\
+				addi	%r1,%r1,4*__SIZEOF_POINTER__	;\
+				ldreg	%r0,__SIZEOF_POINTER__(%r1)	;\
+				mtlr	%r0				;\
+				li	%r3,-1				;\
+				li	%r4,-1				;\
+				blr
+#else	/* !_REENTRANT */
+#define DO_CERROR()		.pushsection ".toc", "aw"		;\
+			.Lerrno:.tc	errno[TC], errno		;\
+				.popsection				;\
+				lwz	%r4,_C_LABEL(.Lerrno)@toc(%r2)	;\
+				stw	%r3,0(%r4)			;\
+				li	%r3,-1				;\
+				li	%r4,-1				;\
+				blr
+#endif	/* _REENTRANT */
+
+#define	BRANCH_TO_CERROR()	DO_CERROR()
 
 #define	_DOSYSCALL(x)		li	%r0,(SYS_ ## x)		;\
 				sc
@@ -19,7 +42,7 @@
 
 #define _SYSCALL(x,y)		.text				;\
 				.p2align 2			;\
-			2:	BRANCH_TO_CERROR()		;\
+			2:	DO_CERROR()			;\
 				_SYSCALL_NOERROR(x,y)		;\
 				bso	2b
 
@@ -33,7 +56,7 @@
 
 #define PSEUDO(x,y)		_SYSCALL_NOERROR(x,y)		;\
 				bnslr				;\
-				BRANCH_TO_CERROR()		;\
+				DO_CERROR()			;\
 				END(x)
 
 #define RSYSCALL_NOERROR(x)	PSEUDO_NOERROR(x,x)