tech-toolchain archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[PATCH] String offset errors on evbarm 8.99 [PR 54159]
PR number: 54159
Description: The BFD GNU binutils linker when invoked for the arm32 elf
target with a dshared linked object sometimes complains about string
offsets in .strtab that are past the end of the section.
How to reproduce: CC and LD have to be set to the arm32_elf programs
(native or hosted).
echo "#include <stdio.h>" >PR54159.h
cat /dev/null >PR54159.exp
for module in a b c d; do
cat <<EOT >$module.c
#include "PR54159.h"
void
$module(void)
{
printf("Hello from $module.\n");
}
EOT
echo "extern void $module(void);" >>PR54159.h
echo "$module" >>PR54159.exp
done
for module in a b c d; do
$CC -I. -fPIC -c -o $module.o $module.c
done
$LD -shared -soname libPR54159.so.0\
-retain-symbols-file ./PR54159.exp\
-o libPR54159.so *.o
Then invoking $LD on libPR54159.so will emit the complaints.
Source of the bug:
The bug was introduced in 2016-08-04:
(elf32_arm_swap_symbol_in): Add detection code for CMSE special
symbols.
The problem is that bfd_elf_sym_name() is invoked inside of
elf32_arm_swap_symbol_in() but this latter has no information,
amongst its parameters, about the correct strings section associated
with a symbol entry (while its caller have).
So bfd_elf_sym_name() was called passing the standard symtab_hdr
that is .strtab, which is wrong when the symbols are the dynamic
ones whose offsets are relative to .dynstr.
Hence, the code verifying that the offset was not past the end of
the section detected that something was wrong only when the .strtab
happened to be shortest than the offsets verified.
So the bug was a permanent one but only seen when .strtab was
shorten, which was the case when -retain-symbols-file was used to
reduce the list of visible symbols.
NOTE: the BFD code limits the size of the strings sections (all) by
only emitting the longest strings but not adding strings that are
suffixes of a longer one. Hence, names like "abcd", "bcd", "cd", "d"
will produce only one entry in a string section: "abcd" since all
the others are suffixes.
For ARM, it can be misleading to see that for example .strtab has
only "$a", "$d", "c" , "b" (in the test case above) "missing" symbol
names "a" and "d". But they are not missing: they are suffix of
resp. "$a" and "$d". No problem here.
Machines concerned:
Only arm32, elf. This renders debugging difficult
and could eventually produce incorrect shared libraries or executable
when there are thumbs and when adding a new module since names could
match (because the wrong strings are used) when they should not.
Solutions discarded:
- Putting the chunk of code in the caller, that has the information
about the correct string table. But the caller is a generic elf.c
function and it would introduce target specific code ruining the
whole purpose of the BFD abstraction;
- Adding another function pointer in the BFD xvec so that no-ops
(for now) for other backends are called and a dedicated function for
arm32, with the correct information amongst the parameters, doing
the job. But it will have to be called just after swap_symbol_in(),
that is linking this "generic" function to this and this is not
general at all. And if it is linked, it better stays inside
swap_symbol_in();
- Trying to refactor elf32-arm.c so that the processing is done
inside the function that has directly or indirectly the information.
But I have not at the moment a sufficient knowledge neither of BDF
or of low level ARM to guess what amount of time will be necessary
to achieve it (and ENOTIME) and it might solve one bug but open a
whole can of worms elsewhere, delaying 9.0 release.
Solution adopted:
The simplest: since the caller of swap_symbol_in() has the
information, I added a supplementary parameter to
swap_symbol_in() to pass the correct symtab_hdr pointer,
modified the calls and added ATTRIBUTE_UNUSED in the
implementations that don't use it.
Pros: it is the simplest and should not alter other targets so not
introduce bugs elsewhere. It solves the problem without touching
anything else in arm32_elf either. It could be argued that this
supplementary parameter could be used for better diagnosing purposes
(hability to print associated name in the swap_symbol_in()
implementations.
Cons: the function has, normally, nothing to do with names. Some
targets now passes NULL instead of correct value---because in some
contexts, the value is not available---which is harmless as long as
somebody doesn't try to add code that assume the value is always
defined in every context.
--
Thierry Laronde <tlaronde +AT+ polynum +dot+ com>
http://www.kergis.com/
http://www.sbfa.fr/
Key fingerprint = 0FF7 E906 FBAF FE95 FD89 250D 52B1 AE95 6006 F40C
Index: external/gpl3/binutils/dist/bfd/elf-bfd.h
===================================================================
RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/elf-bfd.h,v
retrieving revision 1.9
diff -u -r1.9 elf-bfd.h
--- external/gpl3/binutils/dist/bfd/elf-bfd.h 7 Nov 2018 01:13:52 -0000 1.9
+++ external/gpl3/binutils/dist/bfd/elf-bfd.h 15 Aug 2019 07:43:11 -0000
@@ -712,7 +712,7 @@
void (*write_relocs)
(bfd *, asection *, void *);
bfd_boolean (*swap_symbol_in)
- (bfd *, const void *, const void *, Elf_Internal_Sym *);
+ (bfd *, const void *, const void *, Elf_Internal_Sym *, Elf_Internal_Shdr *);
void (*swap_symbol_out)
(bfd *, const Elf_Internal_Sym *, void *, void *);
bfd_boolean (*slurp_reloc_table)
@@ -2348,7 +2348,7 @@
(bfd *);
extern bfd_boolean bfd_elf32_swap_symbol_in
- (bfd *, const void *, const void *, Elf_Internal_Sym *);
+ (bfd *, const void *, const void *, Elf_Internal_Sym *, Elf_Internal_Shdr *);
extern void bfd_elf32_swap_symbol_out
(bfd *, const Elf_Internal_Sym *, void *, void *);
extern void bfd_elf32_swap_reloc_in
@@ -2394,7 +2394,7 @@
(bfd *);
extern bfd_boolean bfd_elf64_swap_symbol_in
- (bfd *, const void *, const void *, Elf_Internal_Sym *);
+ (bfd *, const void *, const void *, Elf_Internal_Sym *, Elf_Internal_Shdr *);
extern void bfd_elf64_swap_symbol_out
(bfd *, const Elf_Internal_Sym *, void *, void *);
extern void bfd_elf64_swap_reloc_in
Index: external/gpl3/binutils/dist/bfd/elf.c
===================================================================
RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/elf.c,v
retrieving revision 1.13
diff -u -r1.13 elf.c
--- external/gpl3/binutils/dist/bfd/elf.c 7 Nov 2018 01:13:52 -0000 1.13
+++ external/gpl3/binutils/dist/bfd/elf.c 15 Aug 2019 07:43:15 -0000
@@ -491,7 +491,7 @@
shndx = extshndx_buf;
isym < isymend;
esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
- if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
+ if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym, symtab_hdr))
{
symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
/* xgettext:c-format */
Index: external/gpl3/binutils/dist/bfd/elf32-arm.c
===================================================================
RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/elf32-arm.c,v
retrieving revision 1.14
diff -u -r1.14 elf32-arm.c
--- external/gpl3/binutils/dist/bfd/elf32-arm.c 5 May 2019 21:49:53 -0000 1.14
+++ external/gpl3/binutils/dist/bfd/elf32-arm.c 15 Aug 2019 07:43:22 -0000
@@ -19626,12 +19626,12 @@
elf32_arm_swap_symbol_in (bfd * abfd,
const void *psrc,
const void *pshn,
- Elf_Internal_Sym *dst)
+ Elf_Internal_Sym *dst,
+ Elf_Internal_Shdr *symtab_hdr)
{
- Elf_Internal_Shdr *symtab_hdr;
const char *name = NULL;
- if (!bfd_elf32_swap_symbol_in (abfd, psrc, pshn, dst))
+ if (!bfd_elf32_swap_symbol_in (abfd, psrc, pshn, dst, symtab_hdr))
return FALSE;
dst->st_target_internal = 0;
@@ -19660,7 +19660,6 @@
ARM_SET_SYM_BRANCH_TYPE (dst->st_target_internal, ST_BRANCH_UNKNOWN);
/* Mark CMSE special symbols. */
- symtab_hdr = & elf_symtab_hdr (abfd);
if (symtab_hdr->sh_size && dst->st_size != 0)
name = bfd_elf_sym_name (abfd, symtab_hdr, dst, NULL);
if (name && CONST_STRNEQ (name, CMSE_PREFIX))
Index: external/gpl3/binutils/dist/bfd/elf32-i386.c
===================================================================
RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/elf32-i386.c,v
retrieving revision 1.11
diff -u -r1.11 elf32-i386.c
--- external/gpl3/binutils/dist/bfd/elf32-i386.c 7 Nov 2018 01:13:52 -0000 1.11
+++ external/gpl3/binutils/dist/bfd/elf32-i386.c 15 Aug 2019 07:43:23 -0000
@@ -3949,7 +3949,7 @@
if (!bed->s->swap_symbol_in (abfd,
(htab->dynsym->contents
+ r_symndx * sizeof (Elf32_External_Sym)),
- 0, &sym))
+ 0, &sym, NULL))
abort ();
if (ELF32_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
Index: external/gpl3/binutils/dist/bfd/elf32-s390.c
===================================================================
RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/elf32-s390.c,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 elf32-s390.c
--- external/gpl3/binutils/dist/bfd/elf32-s390.c 6 Nov 2018 21:18:42 -0000 1.1.1.7
+++ external/gpl3/binutils/dist/bfd/elf32-s390.c 15 Aug 2019 07:43:24 -0000
@@ -3710,7 +3710,7 @@
|| !bed->s->swap_symbol_in (abfd,
(htab->elf.dynsym->contents
+ r_symndx * bed->s->sizeof_sym),
- 0, &sym))
+ 0, &sym, NULL))
abort ();
/* Check relocation against STT_GNU_IFUNC symbol. */
Index: external/gpl3/binutils/dist/bfd/elf32-v850.c
===================================================================
RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/elf32-v850.c,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 elf32-v850.c
--- external/gpl3/binutils/dist/bfd/elf32-v850.c 6 Nov 2018 21:18:35 -0000 1.1.1.7
+++ external/gpl3/binutils/dist/bfd/elf32-v850.c 15 Aug 2019 07:43:26 -0000
@@ -3280,7 +3280,7 @@
bfd_elf32_swap_symbol_in (abfd,
extsyms + ELF32_R_SYM (irel->r_info),
shndx ? shndx + ELF32_R_SYM (irel->r_info) : NULL,
- & isym);
+ & isym, symtab_hdr);
if (isym.st_shndx != sec_shndx)
continue;
@@ -3339,7 +3339,7 @@
{
Elf_Internal_Sym isym;
- bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym);
+ bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym, symtab_hdr);
if (isym.st_shndx == sec_shndx
&& isym.st_value >= addr + count
@@ -3375,7 +3375,7 @@
{
Elf_Internal_Sym isym;
- bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym);
+ bfd_elf32_swap_symbol_in (abfd, esym, shndx, & isym, symtab_hdr);
sym_hash = elf_sym_hashes (abfd) [sym_index];
if (isym.st_shndx == sec_shndx
Index: external/gpl3/binutils/dist/bfd/elf64-s390.c
===================================================================
RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/elf64-s390.c,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 elf64-s390.c
--- external/gpl3/binutils/dist/bfd/elf64-s390.c 6 Nov 2018 21:18:36 -0000 1.1.1.7
+++ external/gpl3/binutils/dist/bfd/elf64-s390.c 15 Aug 2019 07:43:27 -0000
@@ -3507,7 +3507,7 @@
|| !bed->s->swap_symbol_in (abfd,
(htab->elf.dynsym->contents
+ r_symndx * bed->s->sizeof_sym),
- 0, &sym))
+ 0, &sym, NULL))
abort ();
/* Check relocation against STT_GNU_IFUNC symbol. */
Index: external/gpl3/binutils/dist/bfd/elf64-x86-64.c
===================================================================
RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/elf64-x86-64.c,v
retrieving revision 1.9
diff -u -r1.9 elf64-x86-64.c
--- external/gpl3/binutils/dist/bfd/elf64-x86-64.c 7 Nov 2018 01:13:52 -0000 1.9
+++ external/gpl3/binutils/dist/bfd/elf64-x86-64.c 15 Aug 2019 07:43:29 -0000
@@ -4375,7 +4375,7 @@
if (!bed->s->swap_symbol_in (abfd,
(htab->elf.dynsym->contents
+ r_symndx * bed->s->sizeof_sym),
- 0, &sym))
+ 0, &sym, NULL))
abort ();
if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
Index: external/gpl3/binutils/dist/bfd/elfcode.h
===================================================================
RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/elfcode.h,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 elfcode.h
--- external/gpl3/binutils/dist/bfd/elfcode.h 6 Nov 2018 21:18:37 -0000 1.1.1.7
+++ external/gpl3/binutils/dist/bfd/elfcode.h 15 Aug 2019 07:43:29 -0000
@@ -174,7 +174,8 @@
elf_swap_symbol_in (bfd *abfd,
const void *psrc,
const void *pshn,
- Elf_Internal_Sym *dst)
+ Elf_Internal_Sym *dst,
+ Elf_Internal_Shdr *symtab_hdr ATTRIBUTE_UNUSED)
{
const Elf_External_Sym *src = (const Elf_External_Sym *) psrc;
const Elf_External_Sym_Shndx *shndx = (const Elf_External_Sym_Shndx *) pshn;
Index: external/gpl3/binutils/dist/bfd/elfnn-aarch64.c
===================================================================
RCS file: /cvsroot/src/external/gpl3/binutils/dist/bfd/elfnn-aarch64.c,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 elfnn-aarch64.c
--- external/gpl3/binutils/dist/bfd/elfnn-aarch64.c 6 Nov 2018 21:18:35 -0000 1.1.1.5
+++ external/gpl3/binutils/dist/bfd/elfnn-aarch64.c 15 Aug 2019 07:43:36 -0000
@@ -7822,7 +7822,7 @@
if (!bed->s->swap_symbol_in (abfd,
(htab->root.dynsym->contents
+ r_symndx * bed->s->sizeof_sym),
- 0, &sym))
+ 0, &sym, NULL))
{
/* xgettext:c-format */
_bfd_error_handler (_("%pB symbol number %lu references"
Home |
Main Index |
Thread Index |
Old Index