--- eglibc-2.13.old/elf/dl-load.c	2011-02-04 22:13:20.000000000 +0000
+++ eglibc-2.13/elf/dl-load.c	2011-10-11 16:02:16.096679357 +0000
@@ -1547,6 +1551,201 @@
     _dl_debug_printf_c ("\t\t(%s)\n", what);
 }
 
+unsigned long
+read_uleb128 (unsigned char *data, unsigned int *length_return)
+{
+    unsigned long result = 0;
+    unsigned int  num_read = 0;
+    unsigned int  shift = 0;
+    unsigned char byte;
+
+    do
+    {
+        byte = *data++;
+        num_read++;
+
+        result |= ((unsigned long) (byte & 0x7f)) << shift;
+
+        shift += 7;
+
+    }
+    while (byte & 0x80);
+
+    if (length_return != NULL)
+        *length_return = num_read;
+
+    return result;
+}
+
+#define ATTR_TAG_FILE 1
+#define ABI_VFP_args  28
+#define VFP_ARGS_IN_VFP_REGS 1
+
+
+/* Check consistency of ARM attributes. */
+static int
+check_arm_attributes_hfabi(int fd, ElfW(Ehdr) *ehdr, bool *is_hf)
+{
+    unsigned int i;
+    ElfW(Shdr) *shdrs;
+    int sh_size = ehdr->e_shentsize * ehdr->e_shnum;
+
+    /* Load in the section headers so we can look for the attributes
+     * section */
+    shdrs = alloca(sh_size);
+    __lseek (fd, ehdr->e_shoff, SEEK_SET);
+    if ((size_t) __libc_read (fd, (void *) shdrs, sh_size) != sh_size)
+        return -1;
+
+    for (i = 0; i < ehdr->e_shnum; i++)
+    {        
+        if (SHT_ARM_ATTRIBUTES == shdrs[i].sh_type)
+        {
+            /* We've found a likely section. Load the contents and
+             * check the tags */
+            unsigned char *contents = alloca(shdrs[i].sh_size);
+            unsigned char *p = contents;
+            unsigned char * end;
+
+            __lseek (fd, shdrs[i].sh_offset, SEEK_SET);
+            if ((size_t) __libc_read (fd, (void *) contents, shdrs[i].sh_size) != shdrs[i].sh_size)
+                return -1;
+
+            /* Sanity-check the attribute section details. Make sure
+             * that it's the "aeabi" section, that's all we care
+             * about. */
+            if (*p == 'A')
+            {
+                unsigned long len = shdrs[i].sh_size - 1;
+                unsigned long namelen;
+                p++;
+                
+                while (len > 0)
+                {
+                    unsigned long section_len = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
+                    if (section_len > len)
+                    {
+                        _dl_debug_printf_c ("    invalid section len %lu, max remaining %lu\n", section_len, len);
+                        section_len = len;
+                    }
+
+                    p += 4;                    
+                    len -= section_len;
+                    section_len -= 4;
+
+                    if (0 != strcmp((char *)p, "aeabi"))
+                    {
+                        _dl_debug_printf_c ("    ignoring unknown attr section %s\n", p);
+                        p += section_len;
+                        continue;
+                    }
+                    namelen = strlen((char *)p) + 1;
+                    p += namelen;
+                    section_len -= namelen;
+                    
+                    /* We're in a valid section. Walk through this
+                     * section looking for the tag we care about
+                     * (ABI_VFP_args) */
+                    while (section_len > 0)
+                    {
+                        int tag;
+                        int val;
+                        unsigned long size;
+
+                        end = p;
+                        tag = (*p++);
+
+                        size = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
+                        if (size > section_len)
+                        {
+                            _dl_debug_printf_c ("    invalid subsection length %lu, max allowed %lu\n", size, section_len);
+                            size = section_len;
+                        }
+                        p += 4;
+                        
+                        section_len -= size;
+                        end += size;
+                        if (ATTR_TAG_FILE != tag)
+                        {
+                            /* ignore, we don't care */
+                            _dl_debug_printf_c ("    ignoring unknown subsection with type %u length %lu\n", tag, size);
+                            p = end;
+                            continue;
+                        }
+                        while (p < end)
+                        {
+                            unsigned int taglen;
+                            
+                            tag = read_uleb128 (p, &taglen);
+                            p += taglen;
+                            /* Handle the different types of tag. */
+                            if ( (tag == 4) || (tag == 5) || (tag == 67) )
+                            {
+                                /* Special cases for string values */
+                                namelen = strlen((char *)p) + 1;
+                                p += namelen;
+                            }
+                            else
+                            {
+                                val = read_uleb128 (p, &taglen);
+                                p += taglen;
+                            }
+                            if ( (tag == ABI_VFP_args) && (val == VFP_ARGS_IN_VFP_REGS) )
+                            {
+                                *is_hf = 1;
+                                return 0;
+                            }
+                        }
+                    }
+                }
+            }                
+        }            
+    }
+    
+    return 0;
+}
+
+static int
+arm_specific_checks(int fd, const char *name, ElfW(Ehdr) *ehdr)
+{
+    static int all_hf = -1; /* unset */
+    bool is_hf = false;
+    int ret;
+
+    ret = check_arm_attributes_hfabi(fd, ehdr, &is_hf);
+    if (ret != 0)
+        return ret;
+    
+    if (all_hf == -1)
+    {
+        if (is_hf)
+            all_hf = 1;
+        else
+            all_hf = 0;
+        return 0;
+    }
+    else if (all_hf == 1 && !is_hf)
+    {
+      //        _dl_debug_printf_c ("%s: Trying to load a soft-fp ABI object into a hard-fp binary\n", __func__);
+        return 1;
+    }
+    else if (all_hf == 0 && is_hf)
+    {
+      //        _dl_debug_printf_c ("%s: Trying to load a hard-fp ABI object into a soft-fp binary\n", __func__);
+        return 1;
+    }
+}
+
+static int
+arch_specific_checks(int fd, const char *name, ElfW(Ehdr) *ehdr)
+{
+    if (1)
+        return arm_specific_checks(fd, name, ehdr);
+
+    return 0;
+}
+
+
 /* Open a file and verify it is an ELF file for this architecture.  We
    ignore only ELF files for other architectures.  Non-ELF files and
    ELF files with different header information cause fatal errors since
@@ -1745,6 +1944,7 @@
 
       /* Check .note.ABI-tag if present.  */
       for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph)
+      {
 	if (ph->p_type == PT_NOTE && ph->p_filesz >= 32 && ph->p_align >= 4)
 	  {
 	    ElfW(Addr) size = ph->p_filesz;
@@ -1793,6 +1993,17 @@
 	    break;
 	  }
     }
+#ifdef CHECK_HF_ABI
+        if (-1 != fd)
+        {
+            if (arch_specific_checks(fd, name, ehdr))
+            {
+                errstring = N_("architecture-specific checks failed");
+                goto call_lose;
+            }
+        }
+#endif
+    }
 
   return fd;
 }
