This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

-gc-sections for elf32-dlx and possible buglette in elf32-target.h


    Hi all at binutils,

  I'm trying to add -gc-sections to the elf32-dlx target[*].  This is a
somewhat obscure target, but my problems are more to do with implementing
generic ELF support in a backend so I hope someone might be able to give me
a few pointers.

  My first effort was to simply add gc_mark/sweep_hook functions and #def
elf_backend_can_gc_sections.  This didn't actually work, as a quick printf
test showed that neither of the hooks were actually being called.  I
borrowed the gc-sections verbose warning code from the patch that Grant
Edwards posted at the end of last year[**] and that quickly revealed that
is_elf_hash_table was returning zero, and so elf_gc_sections assumed it
couldn't do any work.

  Now my first thought was to simply derive a hash table type from the elf
hash table, add XXX_link_hash_newfunc and XXX_link_hash_table_create
routines based on the bog-standard templates; in particular, the
hash_table_create routine calls out to the _bfd_elf_link_hash_table_init
routine, which should ensure the hash table type is correctly set up.  I
hoped that this would cause all the elf-specific stuff to be pulled in
correctly, and hoped that would convince the linker it was dealing with elf
and make it gc the sections.

  However, what it actually did was to start SEGVing.  I reverted the gc
functions and #defs, leaving only the derived elf hash table type, but it
still failed, so I knew it wasn't actually related to that.

  On debugging, it emerged that the problem was occurring in
_bfd_generic_link_output_symbols.  To be precise, in the loop following the
comment:

  /* Adjust the values of the globally visible symbols, and write out
     local symbols.  */

  What turns out to be happening is that this code looks in the asymbol
struct's udata.p member, hoping to find a pointer back to the hash-table
entry that refers to this symbol.  It then comes to an if ()... clause that
carries this comment:
	      /* Force all references to this symbol to point to
		 the same area in memory.  It is possible that
		 this routine will be called with a hash table
		 other than a generic hash table, so we double
		 check that.  */
	      if (info->hash->creator == input_bfd->xvec)
		{
            if (h->sym != (asymbol *) NULL)
		    *sym_ptr = sym = h->sym;
		}

  And this is where it dies, because it turns out that h->sym has the value
0xffffffff, which is not a legal pointer to a symbol!

  Now, I think this is happening because the hash table is indeed NOT a
generic one, but an ELF link hash table, and therefore has a different
structure with different members; in particular, the h->sym member isn't
there.

  So what I was hoping someone could explain to me is why this comparison
between the info->hash->creator and the input_bfd->xvec should be a test for
generic/non-generic hashtable, and whether my assumption that this clause
should *not* be active in elf targets is correct.

  Searching through the mailing list, I've found what appears to be a
similar problem cropping up in May last year[***] in the opposite direction:
a function was being passed a generic hash table but mistook it for an ELF
hash table because it was using the same kind of test.  So I think this
might be a known gotcha in some way.

  Investigating further, I've just found this comment and code in
elf32-target.h:

---snip---
#ifdef elf_backend_relocate_section
#ifndef bfd_elf32_bfd_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_create _bfd_elf_link_hash_table_create
#endif
#else /* ! defined (elf_backend_relocate_section) */
/* If no backend relocate_section routine, use the generic linker.
   Note - this will prevent the port from being able to use some of
   the other features of the ELF linker, because the generic hash structure
   does not have the fields needed by the ELF linker.  In particular it
   means that linking directly to S-records will not work.  */
#ifndef bfd_elf32_bfd_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_create \
  _bfd_generic_link_hash_table_create
#endif
#ifndef bfd_elf32_bfd_link_add_symbols
#define bfd_elf32_bfd_link_add_symbols	_bfd_generic_link_add_symbols
#endif
#ifndef bfd_elf32_bfd_final_link
#define bfd_elf32_bfd_final_link	_bfd_generic_final_link
#endif
#endif /* ! defined (elf_backend_relocate_section) */
---snip---

  This seems to imply that if you don't define your own
elf_backend_relocate_section code, you get only generic functionality: so I
can see that this might be where the inconsistency arises: because the !
defined (elf_backend_relocate_section) clause only defines those symbols to
the generic routines if they haven't already been defined, it implies that
if you define (e.g.) just the link_hash_table_create, you'll end up with an
inconsistent state where you have a non-generic hash being passed to generic
link/symbols routines.

  Presumably, if that code is going to give you the generic add_symbols and
final_link functions, it shouldn't permit you to have your own hash table
defined: IOW, it should either set all three of those #defs for internal
consistency, or it should error out.

  It seems to me that this means that the port as it originally stood was
kind of half-elf and half-generic; it's an elf target and uses elf files,
but it seems to be somehow using the generic linker.

  Here we get to the main point of my question, which is this:  can I get
the elf linker involved (so as to enable gc-sections) without having to code
my own version of backend_relocate_section ?  Or to put it another way,
what's the minimal set of routines that I have to write in addition to the
derived elf hashtable in order to get a consistent and working backend that
uses the ELF link routines?

  I appreciate that this may be a kind of tricky question to ask of anyone
who hasn't worked with that particular backend, but I'm hoping it's generic
enough in terms of all the other ELF backends that someone might be able to
give me just a couple of pointers.  If I can get gc-sections working for
this target, I will of course contribute a patch back as a mark of my
gratitude to the binutils team!


    cheers, 
      DaveK
-- 
[*] contributed by Kuang in q2 2002 (see e.g.
http://sources.redhat.com/ml/binutils/2002-04/msg00163.html or search for
'kuang' in the ml archive).
[**] http://sources.redhat.com/ml/binutils/2003-12/msg00426.html
[***] Discussed by Daniel Jacobowitz and Nick Clifton in
http://sources.redhat.com/ml/binutils/2003-05/msg00628.html and
http://sources.redhat.com/ml/binutils/2003-06/msg00040.html


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]