From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8670 invoked by alias); 3 Dec 2012 15:42:18 -0000 Received: (qmail 8550 invoked by uid 22791); 3 Dec 2012 15:42:15 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from cheddar.halon.org.uk (HELO cheddar.halon.org.uk) (217.10.144.130) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 03 Dec 2012 15:42:07 +0000 Received: from bsmtp by cheddar.halon.org.uk with local-bsmtp (Exim 4.72) (envelope-from ) id 1TfY9m-0003YK-AO; Mon, 03 Dec 2012 15:42:06 +0000 Received: from steve by tack.local with local (Exim 4.80) (envelope-from ) id 1TfY9a-0003Dc-V4; Mon, 03 Dec 2012 15:41:55 +0000 Date: Mon, 03 Dec 2012 15:42:00 -0000 From: Steve McIntyre To: libc-ports@sourceware.org Cc: Carlos O'Donell , "Joseph S. Myers" , Marcus Shawcroft Subject: [PATCH] ARM: Identify the hard-float ABI in older ARM binaries Message-ID: <20121203154154.GF22509@einval.com> References: <20121203153446.GD22509@einval.com> <20121203153747.GE22509@einval.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20121203153747.GE22509@einval.com> X-attached: none User-Agent: Mutt/1.5.21 (2010-09-15) Mailing-List: contact libc-ports-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: libc-ports-owner@sourceware.org X-SW-Source: 2012-12/txt/msg00005.txt.bz2 Hi, I expect this one to be more controversial and I'll understand if people don't want to accept it! It's a variation on the code that's in use today in Debian/Ubuntu to be able to distinguish between soft- and hard-float ABI libraries. In time, the new ELF flags will make this obsolete. Until that time, this adds a fallback for older binaries created before those flags went into binutils. ============================== Identify the hard-float ABI in older ARM binaries * ports/sysdeps/unix/sysv/linux/arm/readelflib.c (read_uleb128): New function. (is_library_hf): Ditto. (process_elf_file): Call is_library_hf() to detect HF ABI if we don't have clear evidence from the ELF flags. Signed-off-by: Steve McIntyre --- ports/sysdeps/unix/sysv/linux/arm/readelflib.c | 129 ++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/ports/sysdeps/unix/sysv/linux/arm/readelflib.c b/ports/sysdeps/unix/sysv/linux/arm/readelflib.c index e4ba2b0..0287644 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/readelflib.c +++ b/ports/sysdeps/unix/sysv/linux/arm/readelflib.c @@ -25,6 +25,133 @@ int process_elf64_file (const char *file_name, const char *lib, int *flag, unsigned int *osversion, char **soname, void *file_contents, size_t file_length); +#undef __ELF_NATIVE_CLASS +#define __ELF_NATIVE_CLASS 32 + +/* Read an unsigned leb128 value from P, store the value in VAL, return + P incremented past the value. We assume that a word is large enough to + hold any value so encoded; if it is smaller than a pointer on some target, + pointers should not be leb128 encoded on that target. */ +static const unsigned char * +read_uleb128 (const unsigned char *p, unsigned long *val) +{ + unsigned int shift = 0; + unsigned char byte; + unsigned long result; + + result = 0; + do + { + byte = *p++; + result |= (byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + *val = result; + return p; +} + +#define ATTR_TAG_FILE 1 +#define ABI_VFP_args 28 +#define VFP_ARGS_IN_VFP_REGS 1 + +/* Check the ABI in the ARM attributes. Search through the section + headers looking for the ARM attributes section, then check the + VFP_ARGS attribute. */ +static int is_library_hf(const char *file_name, void *file_contents, size_t file_length) +{ + unsigned int i; + ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *) file_contents; + ElfW(Shdr) *shdrs; + + shdrs = file_contents + ehdr->e_shoff; + 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 *p = (unsigned char *)file_contents + shdrs[i].sh_offset; + unsigned char * end; + + /* 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) + section_len = len; + + p += 4; + len -= section_len; + section_len -= 4; + + if (0 != strcmp((char *)p, "aeabi")) + { + 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) + { + unsigned long tag, val = 0; + unsigned long size; + + end = p; + tag = (*p++); + size = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; + if (size > section_len) + size = section_len; + p += 4; + + section_len -= size; + end += size; + if (ATTR_TAG_FILE != tag) + { + /* ignore, we don't care */ + p = end; + continue; + } + while (p < end) + { + p = read_uleb128 (p, &tag); + /* 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 + { + p = read_uleb128 (p, &val); + } + if ( (tag == ABI_VFP_args) && (val == VFP_ARGS_IN_VFP_REGS) ) + return 1; + } + } + } + } + } + } + return 0; +} + + /* Returns 0 if everything is ok, != 0 in case of error. */ int process_elf_file (const char *file_name, const char *lib, int *flag, @@ -47,6 +174,8 @@ process_elf_file (const char *file_name, const char *lib, int *flag, *flag = FLAG_ARM_LIBHF|FLAG_ELF_LIBC6; else if (elf32_header->e_flags & EF_ARM_ABI_FLOAT_SOFT) *flag = FLAG_ELF_LIBC6; + else if (is_library_hf(file_name, file_contents, file_length)) + *flag = FLAG_ARM_LIBHF|FLAG_ELF_LIBC6; } } else -- 1.7.10.4 Cheers, -- Steve McIntyre steve.mcintyre@linaro.org Linaro.org | Open source software for ARM SoCs