This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] S/390: Add runtime check for the highgprs kernel feature -unified diff this time


Hi,

I (again) forgot to switch from my gcc quiltrc to the glibc variant.
So the patch was context diff - sorry for that.  Here the same as
unified diff.  Since I've only added lines the difference isn't that
big - so I didn't notice.

My lengthy patch description however stays the same:
http://sources.redhat.com/ml/libc-alpha/2010-01/msg00033.html

Bye,

-Andreas-


2010-01-15  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* sysdeps/s390/s390-32/elf/start.S (_start): Added check for the
	high gprs kernel facility.
	* sysdeps/s390/s390-32/dl-machine.h (elf_machine_matches_host):
	Added high gprs check for DSOs.
	* elf/elf.h (EF_S390_HIGH_GPRS): Added macro definition for the
	new elf header flag.


Index: glibc/sysdeps/s390/s390-32/elf/start.S
===================================================================
--- glibc.orig/sysdeps/s390/s390-32/elf/start.S	2010-01-13 14:26:28.000000000 +0100
+++ glibc/sysdeps/s390/s390-32/elf/start.S	2010-01-15 12:27:18.000000000 +0100
@@ -59,6 +59,88 @@
 	.globl _start
 	.type _start,@function
 _start:
+	/* Check if the kernel provides highgprs facility if needed by
+	   the binary.  */
+
+	lr	%r6,%r15
+	la	%r6,4(%r6)     /* Skip the argument counter.  */
+
+.L11:	l	%r5,0(%r6)     /* Skip the argument vector.  */
+	la	%r6,4(%r6)
+	ltr	%r5,%r5
+	jne	.L11
+
+.L12:	l	%r5,0(%r6)     /* Skip the environment vector.  */
+	la	%r6,4(%r6)
+	ltr	%r5,%r5
+	jne	.L12
+
+	/* Obtain the needed values from the auxiliary vector.  */
+
+	lhi	%r7,16	       /* AT_HWCAP */
+	lhi	%r8,3	       /* AT_PHDR */
+	lhi	%r9,5          /* AT_PHNUM */
+	lhi	%r2,4          /* AT_PHENT */
+.L13:	l	%r5,0(%r6)
+	clr	%r5,%r7
+	jne	.L15
+	l	%r10,4(%r6)    /* r10 = AT_HWCAP value.  */
+.L15:	clr	%r5,%r8
+	jne	.L16
+	l	%r11,4(%r6)    /* r11 = AT_PHDR value.  */
+.L16:	clr	%r5,%r9
+	jne	.L17
+	l	%r12,4(%r6)    /* r12 = AT_PHNUM value.  */
+.L17:	clr	%r5,%r2
+	jne	.L18
+	l	%r0,4(%r6)     /* r0 = AT_PHENT value.  */
+.L18:	ltr	%r5,%r5
+	la	%r6,8(%r6)
+	jnz	.L13
+
+	/* Locate the ELF header by looking for the first PT_LOAD
+	   segment with a p_offset of zero.  */
+
+	lr	%r4,%r11       /* Backup AT_PHDR.  */
+	lhi	%r7,1          /* PT_LOAD id */
+	lhi	%r8,0
+.L19:	cl	%r7,0(%r4)     /* p_type == PT_LOAD? */
+	jne	.L20
+	cl	%r8,4(%r4)     /* p_offset == 0? */
+	jne	.L20
+	l	%r9,8(%r4)     /* r9 = p_vaddr <- ELF header address  */
+	j	.L24
+.L20:	alr	%r4,%r0        /* r4 += AT_PHENT value */
+	brct	%r12,.L19
+
+	j	.+2            /* Trap, there must be such a phdr.  */
+
+.L24:	lr	%r4,%r11       /* Backup AT_PHDR.  */
+	lhi	%r2,6          /* PT_PHDR id */
+.L23:	cl	%r2,0(%r4)
+	jne	.L22
+	l	%r3,8(%r4)     /* r3 = PT_PHDR p_vaddr */
+	j	.L25
+.L22:	alr	%r4,%r0        /* r4 += AT_PHENT value */
+	brct	%r12,.L23
+
+	ltr	%r9,%r9        /* Load address == 0? */
+	jz	.L14           /* No checking for PIE without PT_PHDR.  */
+	j	.L21
+
+.L25:	clr	%r3,%r11       /* PT_PHDR p_vaddr == AT_PHDR? */
+	je	.L21
+	lr	%r9,%r11
+	slr	%r9,%r3        /* elf_header_addr = AT_PHDR - PT_PHDR.p_vaddr */
+
+.L21:	l	%r5,36(%r9)    /* Load the e_flags field.  */
+	tml	%r5,1
+	jz	.L14	       /* Binary does not require highgprs facility.  */
+
+	tml	%r10,512       /* Check the AT_HWCAP value.  */
+	jz	2              /* Trap if no highgprs facility available.  */
+.L14:
+
 	/* Setup pointer to literal pool of _start */
 	basr    %r13,0
 .L0:    ahi     %r13,.Llit-.L0
Index: glibc/elf/elf.h
===================================================================
--- glibc.orig/elf/elf.h	2010-01-13 14:26:28.000000000 +0100
+++ glibc/elf/elf.h	2010-01-15 11:13:47.000000000 +0100
@@ -2493,6 +2493,12 @@ typedef Elf32_Addr Elf32_Conflict;
 /* Keep this the last entry.  */
 #define	R_SH_NUM		256
 
+/* S/390 specific definitions.  */
+
+/* Valid values for the e_flags field.  */
+
+#define EF_S390_HIGH_GPRS    0x00000001  /* High GPRs kernel facility needed.  */
+
 /* Additional s390 relocs */
 
 #define R_390_NONE		0	/* No reloc.  */
Index: glibc/sysdeps/s390/s390-32/dl-machine.h
===================================================================
--- glibc.orig/sysdeps/s390/s390-32/dl-machine.h	2010-01-13 14:26:28.000000000 +0100
+++ glibc/sysdeps/s390/s390-32/dl-machine.h	2010-01-15 11:15:02.000000000 +0100
@@ -27,6 +27,7 @@
 #include <sys/param.h>
 #include <string.h>
 #include <link.h>
+#include <sysdeps/s390/dl-procinfo.h>
 
 /* This is an older, now obsolete value.  */
 #define EM_S390_OLD	0xA390
@@ -35,6 +36,12 @@
 static inline int
 elf_machine_matches_host (const Elf32_Ehdr *ehdr)
 {
+  /* Check if the kernel provides the high gpr facility if needed by
+     the binary.  */
+  if ((ehdr->e_flags & EF_S390_HIGH_GPRS)
+      && !(GLRO (dl_hwcap) & HWCAP_S390_HIGH_GPRS))
+    return 0;
+
   return (ehdr->e_machine == EM_S390 || ehdr->e_machine == EM_S390_OLD)
          && ehdr->e_ident[EI_CLASS] == ELFCLASS32;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]