/390: Add runtime check for the highgprs kernel feature.
authorAndreas Krebbel <Andreas.Krebbel@de.ibm.com>
Fri, 15 Jan 2010 17:10:44 +0000 (09:10 -0800)
committerUlrich Drepper <drepper@redhat.com>
Fri, 15 Jan 2010 17:10:44 +0000 (09:10 -0800)
elf/elf.h
sysdeps/s390/s390-32/dl-machine.h
sysdeps/s390/s390-32/elf/start.S

index 1bc8ef3..8af7c17 100644 (file)
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -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 251a5f6..415b388 100644 (file)
@@ -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
 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 f729010..066f7f0 100644 (file)
        .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