[patch] PPC small data symbols in shared libraries.

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[patch] PPC small data symbols in shared libraries.

Paul Brook
I have some third party ppc shared libraries that export the _SDA_BASE_ and
_SDA2_BASE_. The list of offending libraries includes the vxworks libc, so
fixing the libraries isn't really an option.

With old versions of binutils ld unconditionally provided definitions of these
symbols in executables, so this didn't matter.

With newer binutils these symbols are only provided in executables if they
don't already exist. This means the definitions imported from the shared
library get used, and things break.

The attached patch fixes this by ignoring definitions of these symbols
imported from shared libraries.

Tested --enable-targets=all on ppc-linux and ppc-vxworks.
Ok?

Paul

2005-06-28  Paul Brook  <[hidden email]>

        * elf32-ppc.c (ppc_elf_add_symbol_hook): Ignore small data section
        synbols.

patch.sda_import (778 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [patch] PPC small data symbols in shared libraries.

Eric Christopher

>  {
> +  /* Ignore small data symbols exported from shared libraries.  */
> +  if ((abfd->flags & DYNAMIC) != 0
> +      && (strcmp (*namep, "_SDA_BASE_") == 0
> +         || strcmp (*namep, "_SDA2_BASE_") == 0))
>
I'd make the comment clearer about why we're ignoring them.

-eric

Reply | Threaded
Open this post in threaded view
|

Re: [patch] PPC small data symbols in shared libraries.

Paul Brook
On Tuesday 28 June 2005 22:44, Eric Christopher wrote:
> >  {
> > +  /* Ignore small data symbols exported from shared libraries.  */
> > +  if ((abfd->flags & DYNAMIC) != 0
> > +      && (strcmp (*namep, "_SDA_BASE_") == 0
> > +         || strcmp (*namep, "_SDA2_BASE_") == 0))
>
> I'd make the comment clearer about why we're ignoring them.

Attached patch does this. No functional changes.

Ok?

Paul

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.163
diff -u -p -r1.163 elf32-ppc.c
--- bfd/elf32-ppc.c 23 May 2005 16:22:25 -0000 1.163
+++ bfd/elf32-ppc.c 28 Jun 2005 20:25:51 -0000
@@ -2617,6 +2729,17 @@ ppc_elf_add_symbol_hook (bfd *abfd,
  asection **secp,
  bfd_vma *valp)
 {
+  /* Ignore small data symbols exported from shared libraries.
+     Small data sections are only meaningful in executables, but some
+     (arguably broken) shared libraries export the base symbols anyway.  */
+  if ((abfd->flags & DYNAMIC) != 0
+      && (strcmp (*namep, "_SDA_BASE_") == 0
+  || strcmp (*namep, "_SDA2_BASE_") == 0))
+    {
+      *namep = NULL;
+      return TRUE;
+    }
+
   if (sym->st_shndx == SHN_COMMON
       && !info->relocatable
       && sym->st_size <= elf_gp_size (abfd)
Reply | Threaded
Open this post in threaded view
|

Re: [patch] PPC small data symbols in shared libraries.

Alan Modra
In reply to this post by Paul Brook
On Tue, Jun 28, 2005 at 10:37:06PM +0100, Paul Brook wrote:
> I have some third party ppc shared libraries that export the _SDA_BASE_ and
> _SDA2_BASE_. The list of offending libraries includes the vxworks libc, so
> fixing the libraries isn't really an option.
>
> With old versions of binutils ld unconditionally provided definitions of these
> symbols in executables, so this didn't matter.

I think we should change _bfd_elf_provide_symbol (and
_bfd_elf_provide_section_bound_symbols) to define the symbols if
def_regular is not set.  eg. in _bfd_elf_provide_symbol

  if (h != NULL && !h->def_regular)
    bfd_elf_set_symbol (h, val);

Patch to do this preapproved.  Please update the comments also.

The problem you found with _SDA_BASE_ may also affect other symbols,
like _GLOBAL_OFFSET_TABLE_.

--
Alan Modra
IBM OzLabs - Linux Technology Centre
Reply | Threaded
Open this post in threaded view
|

Re: [patch] PPC small data symbols in shared libraries.

Paul Brook
On Wednesday 29 June 2005 07:44, Alan Modra wrote:

> On Tue, Jun 28, 2005 at 10:37:06PM +0100, Paul Brook wrote:
> > I have some third party ppc shared libraries that export the _SDA_BASE_
> > and _SDA2_BASE_. The list of offending libraries includes the vxworks
> > libc, so fixing the libraries isn't really an option.
> >
> > With old versions of binutils ld unconditionally provided definitions of
> > these symbols in executables, so this didn't matter.
>
> I think we should change _bfd_elf_provide_symbol (and
> _bfd_elf_provide_section_bound_symbols) to define the symbols if
> def_regular is not set.  eg. in _bfd_elf_provide_symbol
>
>   if (h != NULL && !h->def_regular)
>     bfd_elf_set_symbol (h, val);
>
> Patch to do this preapproved.  Please update the comments also.
>
> The problem you found with _SDA_BASE_ may also affect other symbols,
> like _GLOBAL_OFFSET_TABLE_.

I tried this, it doesn't work. _bfd_elf_provide_symbol seems to be too late.
We have already created external relocations against _SDA_BASE_. I couldn't
figure out how to remove these relocation entries after the symbol was forced
local.

Paul
Reply | Threaded
Open this post in threaded view
|

Re: [patch] PPC small data symbols in shared libraries.

Alan Modra
On Wed, Jun 29, 2005 at 05:53:53PM +0100, Paul Brook wrote:
> We have already created external relocations against _SDA_BASE_. I couldn't

Details?  I'd like to know exactly what is going on.  Some solution
other than more code in add_symbol_hook might spring to mind.

--
Alan Modra
IBM OzLabs - Linux Technology Centre
Reply | Threaded
Open this post in threaded view
|

Re: [patch] PPC small data symbols in shared libraries.

Paul Brook
On Wednesday 29 June 2005 20:55, Alan Modra wrote:
> On Wed, Jun 29, 2005 at 05:53:53PM +0100, Paul Brook wrote:
> > We have already created external relocations against _SDA_BASE_. I
> > couldn't
>
> Details?  I'd like to know exactly what is going on.  Some solution
> other than more code in add_symbol_hook might spring to mind.

ppc_elf_adjust_dynamic_symbol allocates space for a copy reloc.
Around line 4130, below the comment
  /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to
     copy the initial value out of the dynamic object and into the

To reproduce the problem (on ppc-linux):

$ cat > foo.c << EOF
int _SDA_BASE_ = 22;
EOF
$ gcc -shared -o foo.so foo.c -nostdlib
$ cat > test.c << EOF
int i=4;
extern char _SDA_BASE_[];
int _start()
{
  i = 42;
  return (int)_SDA_BASE_;
}
EOF
$ gcc -O2 -c test.c
$ ld/ld-new test.o foo.so
$ readelf -r a.out
Relocation section '.rela.dyn' at offset 0x1c8 contains 1 entries:
 Offset     Info    Type            Sym.Value  Sym. Name + Addend
00000000  00000000 R_PPC_NONE                                   00000000

Without this patch this is an R_PPC_COPY reloc against _SDA_BASE_, which is
equally wrong. With add_symbol_hook change we get no relocations in the
output file (the desired behavior).

Paul
Reply | Threaded
Open this post in threaded view
|

Re: [patch] PPC small data symbols in shared libraries.

Alan Modra
I'm about to commit this for the _SDA_BASE_ problem.  It's rather more
complicated than Paul's fix via add_symbol_hook, but should result in
better execution time.

        * elf32-ppc.c (ppc_elf_adjust_dynamic_symbol): Ignore dynamic
        _SDA_BASE_ and _SDA2_BASE_ symbols.
        * elflink.c (_bfd_elf_provide_symbol): Correct comment.  Define
        sym if not def_regular.
        (_bfd_elf_provide_section_bound_symbols): Similarly.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.165
diff -u -p -r1.165 elf32-ppc.c
--- bfd/elf32-ppc.c 29 Jun 2005 13:16:43 -0000 1.165
+++ bfd/elf32-ppc.c 30 Jun 2005 06:11:33 -0000
@@ -3945,6 +3945,24 @@ ppc_elf_adjust_dynamic_symbol (struct bf
   /* This is a reference to a symbol defined by a dynamic object which
      is not a function.  */
 
+  /* First, a fudge for old shared libs that export some symbols they
+     should not.  */
+  if (!h->def_regular
+      && (strcmp (h->root.root.string, "_SDA_BASE_") == 0
+  || strcmp (h->root.root.string, "_SDA2_BASE_") == 0))
+    {
+      /* These symbols will be defined later, as if they were defined in
+ a linker script.  We don't want to use a definition in a shared
+ object.  */
+      const struct elf_backend_data *bed;
+
+      bed = get_elf_backend_data (htab->elf.dynobj);
+      (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+      h->root.type = bfd_link_hash_undefined;
+      h->root.u.undef.abfd = htab->elf.dynobj;
+      return TRUE;
+    }
+
   /* If we are creating a shared library, we must presume that the
      only references to the symbol are via the global offset table.
      For such cases we need not do anything here; the relocations will
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.171
diff -u -p -r1.171 elflink.c
--- bfd/elflink.c 29 Jun 2005 14:05:19 -0000 1.171
+++ bfd/elflink.c 30 Jun 2005 06:11:38 -0000
@@ -9836,8 +9836,9 @@ bfd_elf_set_symbol (struct elf_link_hash
   h->forced_local = 1;
 }
 
-/* Set NAME to VAL if the symbol exists and is undefined.  If val is NULL
-   it is an absolute symbol, otherwise it is relative to that section.  */
+/* Set NAME to VAL if the symbol exists and is not defined in a regular
+   object file.  If S is NULL it is an absolute symbol, otherwise it is
+   relative to that section.  */
 
 void
 _bfd_elf_provide_symbol (struct bfd_link_info *info, const char *name,
@@ -9847,13 +9848,12 @@ _bfd_elf_provide_symbol (struct bfd_link
 
   h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE,
     FALSE);
-  if (h != NULL && (h->root.type == bfd_link_hash_undefined
-    || h->root.type == bfd_link_hash_undefweak))
+  if (h != NULL && !h->def_regular)
     bfd_elf_set_symbol (h, val, s);
 }
 
-/* Set START and END to boundaries of SEC if they exist and are
-   undefined.  */
+/* Set START and END to boundaries of SEC if they exist and are not
+   defined in regular object files.  */
 
 void
 _bfd_elf_provide_section_bound_symbols (struct bfd_link_info *info,
@@ -9868,15 +9868,11 @@ _bfd_elf_provide_section_bound_symbols (
   /* Check if we need them or not first.  */
   hs = elf_link_hash_lookup (elf_hash_table (info), start, FALSE,
      FALSE, FALSE);
-  do_start = (hs != NULL
-      && (hs->root.type == bfd_link_hash_undefined
-  || hs->root.type == bfd_link_hash_undefweak));
+  do_start = hs != NULL && !hs->def_regular;
 
   he = elf_link_hash_lookup (elf_hash_table (info), end, FALSE,
      FALSE, FALSE);
-  do_end = (he != NULL
-    && (he->root.type == bfd_link_hash_undefined
- || he->root.type == bfd_link_hash_undefweak));
+  do_end = he != NULL && !he->def_regular;
 
   if (!do_start && !do_end)
     return;

--
Alan Modra
IBM OzLabs - Linux Technology Centre