OSDN Git Service

* elf-bfd.h (struct got_entry, struct plt_entry): Forward declare.
authorAlan Modra <amodra@bigpond.net.au>
Tue, 4 Feb 2003 12:49:57 +0000 (12:49 +0000)
committerAlan Modra <amodra@bigpond.net.au>
Tue, 4 Feb 2003 12:49:57 +0000 (12:49 +0000)
(struct elf_link_hash_entry): Add "glist" and "plist" fields to
"got" union, and declare as gotplt_union.  Use gotplt_uinion for
"plt" field.
(struct elf_link_hash_table): Make "init_refcount" a gotplt_union.
Add "init_offset" field.
(struct elf_obj_tdata <local_got>): Add "struct got_entry **" to union.
(elf_local_got_ents): Declare.
* elf.c (_bfd_elf_link_hash_newfunc): Adjust initialization of "got"
and "plt".
(_bfd_elf_link_hash_hide_symbol): Use "init_offset".
(_bfd_elf_link_hash_table_init): Set "init_offset".
* elflink.h (NAME(bfd_elf,size_dynamic_sections)): Set init_refcount
from init_offset.
(elf_adjust_dynamic_symbol): Set plt and got offsets using init_offset.

* elf.c (bfd_elf_local_sym_name): Split out from..
(group_signature): ..here.
* elf-bfd.h (bfd_elf_local_sym_name): Declare.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf.c
bfd/elflink.h

index 21d22b3..2077794 100644 (file)
@@ -1,5 +1,27 @@
 2003-02-04  Alan Modra  <amodra@bigpond.net.au>
 
+       * elf-bfd.h (struct got_entry, struct plt_entry): Forward declare.
+       (struct elf_link_hash_entry): Add "glist" and "plist" fields to
+       "got" union, and declare as gotplt_union.  Use gotplt_uinion for
+       "plt" field.
+       (struct elf_link_hash_table): Make "init_refcount" a gotplt_union.
+       Add "init_offset" field.
+       (struct elf_obj_tdata <local_got>): Add "struct got_entry **" to union.
+       (elf_local_got_ents): Declare.
+       * elf.c (_bfd_elf_link_hash_newfunc): Adjust initialization of "got"
+       and "plt".
+       (_bfd_elf_link_hash_hide_symbol): Use "init_offset".
+       (_bfd_elf_link_hash_table_init): Set "init_offset".
+       * elflink.h (NAME(bfd_elf,size_dynamic_sections)): Set init_refcount
+       from init_offset.
+       (elf_adjust_dynamic_symbol): Set plt and got offsets using init_offset.
+
+       * elf.c (bfd_elf_local_sym_name): Split out from..
+       (group_signature): ..here.
+       * elf-bfd.h (bfd_elf_local_sym_name): Declare.
+
+2003-02-04  Alan Modra  <amodra@bigpond.net.au>
+
        * elf-bfd.h (enum elf_link_info_type): Remove.
        (struct bfd_elf_section_data): Move sec_info_type, use_rela_p fields
        to struct sec.  Remove linkonce_p field.
index 8c401b5..2e5587c 100644 (file)
@@ -80,6 +80,8 @@ typedef struct
 } elf_symbol_type;
 \f
 struct elf_strtab_hash;
+struct got_entry;
+struct plt_entry;
 
 /* ELF linker hash table entries.  */
 
@@ -146,23 +148,23 @@ struct elf_link_hash_entry
 
   /* If this symbol requires an entry in the global offset table, the
      processor specific backend uses this field to track usage and
-     final offset.  We use a union and two names primarily to document
-     the intent of any particular piece of code.  The field should be
-     used as a count until size_dynamic_sections, at which point the
-     contents of the .got is fixed.  Afterward, if this field is -1,
-     then the symbol does not require a global offset table entry.  */
-  union
+     final offset.  Two schemes are supported:  The first assumes that
+     a symbol may only have one GOT entry, and uses REFCOUNT until
+     size_dynamic_sections, at which point the contents of the .got is
+     fixed.  Afterward, if OFFSET is -1, then the symbol does not
+     require a global offset table entry.  The second scheme allows
+     multiple GOT entries per symbol, managed via a linked list
+     pointed to by GLIST.  */
+  union gotplt_union
     {
       bfd_signed_vma refcount;
       bfd_vma offset;
+      struct got_entry *glist;
+      struct plt_entry *plist;
     } got;
 
   /* Same, but tracks a procedure linkage table entry.  */
-  union
-    {
-      bfd_signed_vma refcount;
-      bfd_vma offset;
-    } plt;
+  union gotplt_union plt;
 
   /* Symbol size.  */
   bfd_size_type size;
@@ -323,9 +325,13 @@ struct elf_link_hash_table
 
   /* The value to use when initialising got.refcount/offset and
      plt.refcount/offset in an elf_link_hash_entry.  Set to zero when
-     the values are refcounts.  Set to -1 in size_dynamic_sections
-     when the values may be offsets.  */
-  bfd_signed_vma init_refcount;
+     the values are refcounts.  Set to init_offset in
+     size_dynamic_sections when the values may be offsets.  */
+  union gotplt_union init_refcount;
+
+  /* The value to use for got.refcount/offset and plt.refcount/offset
+     when the values may be offsets.  Normally (bfd_vma) -1.  */
+  union gotplt_union init_offset;
 
   /* The number of symbols found in the link which must be put into
      the .dynsym section.  */
@@ -1099,17 +1105,14 @@ struct elf_obj_tdata
      minus the sh_info field of the symbol table header.  */
   struct elf_link_hash_entry **sym_hashes;
 
-  /* A mapping from local symbols to offsets into the global offset
-     table, used when linking.  This is indexed by the symbol index.
-     Like for the globals, we use a union and two names primarily to
-     document the intent of any particular piece of code.  The field
-     should be used as a count until size_dynamic_sections, at which
-     point the contents of the .got is fixed.  Afterward, if an entry
-     is -1, then the symbol does not require a global offset table entry.  */
+  /* Track usage and final offsets of GOT entries for local symbols.
+     This array is indexed by symbol index.  Elements are used
+     identically to "got" in struct elf_link_hash_entry.  */
   union
     {
       bfd_signed_vma *refcounts;
       bfd_vma *offsets;
+      struct got_entry **ents;
     } local_got;
 
   /* A mapping from local symbols to offsets into the various linker
@@ -1216,6 +1219,7 @@ struct elf_obj_tdata
 #define elf_sym_hashes(bfd)    (elf_tdata(bfd) -> sym_hashes)
 #define elf_local_got_refcounts(bfd) (elf_tdata(bfd) -> local_got.refcounts)
 #define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got.offsets)
+#define elf_local_got_ents(bfd) (elf_tdata(bfd) -> local_got.ents)
 #define elf_local_ptr_offsets(bfd) (elf_tdata(bfd) -> linker_section_pointers)
 #define elf_dt_name(bfd)       (elf_tdata(bfd) -> dt_name)
 #define elf_dt_soname(bfd)     (elf_tdata(bfd) -> dt_soname)
@@ -1253,6 +1257,8 @@ extern char *bfd_elf_get_str_section
 extern Elf_Internal_Sym *bfd_elf_get_elf_syms
   PARAMS ((bfd *, Elf_Internal_Shdr *, size_t, size_t,
           Elf_Internal_Sym *, PTR, Elf_External_Sym_Shndx *));
+extern const char *bfd_elf_local_sym_name
+  PARAMS ((bfd *, Elf_Internal_Sym *));
 
 extern bfd_boolean _bfd_elf_copy_private_bfd_data
   PARAMS ((bfd *, bfd *));
index c4c6487..be0025d 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -476,6 +476,23 @@ bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, symoffset,
   return intsym_buf;
 }
 
+/* Look up a symbol name.  */
+const char *
+bfd_elf_local_sym_name (abfd, isym)
+     bfd *abfd;
+     Elf_Internal_Sym *isym;
+{
+  unsigned int iname = isym->st_name;
+  unsigned int shindex = elf_tdata (abfd)->symtab_hdr.sh_link;
+  if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+    {
+      iname = elf_elfsections (abfd)[isym->st_shndx]->sh_name;
+      shindex = elf_elfheader (abfd)->e_shstrndx;
+    }
+
+  return bfd_elf_string_from_elf_section (abfd, shindex, iname);
+}
+
 /* Elf_Internal_Shdr->contents is an array of these for SHT_GROUP
    sections.  The first element is the flags, the rest are section
    pointers.  */
@@ -497,8 +514,6 @@ group_signature (abfd, ghdr)
   unsigned char esym[sizeof (Elf64_External_Sym)];
   Elf_External_Sym_Shndx eshndx;
   Elf_Internal_Sym isym;
-  unsigned int iname;
-  unsigned int shindex;
 
   /* First we need to ensure the symbol table is available.  */
   if (! bfd_section_from_shdr (abfd, ghdr->sh_link))
@@ -510,16 +525,7 @@ group_signature (abfd, ghdr)
                            &isym, esym, &eshndx) == NULL)
     return NULL;
 
-  /* Look up the symbol name.  */
-  iname = isym.st_name;
-  shindex = hdr->sh_link;
-  if (iname == 0 && ELF_ST_TYPE (isym.st_info) == STT_SECTION)
-    {
-      iname = elf_elfsections (abfd)[isym.st_shndx]->sh_name;
-      shindex = elf_elfheader (abfd)->e_shstrndx;
-    }
-
-  return bfd_elf_string_from_elf_section (abfd, shindex, iname);
+  return bfd_elf_local_sym_name (abfd, &isym);
 }
 
 /* Set next_in_group list pointer, and group name for NEWSECT.  */
@@ -1420,8 +1426,8 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
       ret->vtable_entries_size = 0;
       ret->vtable_entries_used = NULL;
       ret->vtable_parent = NULL;
-      ret->got.refcount = htab->init_refcount;
-      ret->plt.refcount = htab->init_refcount;
+      ret->got = htab->init_refcount;
+      ret->plt = htab->init_refcount;
       ret->size = 0;
       ret->type = STT_NOTYPE;
       ret->other = 0;
@@ -1496,7 +1502,7 @@ _bfd_elf_link_hash_hide_symbol (info, h, force_local)
      struct elf_link_hash_entry *h;
      bfd_boolean force_local;
 {
-  h->plt.offset = (bfd_vma) -1;
+  h->plt = elf_hash_table (info)->init_offset;
   h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
   if (force_local)
     {
@@ -1526,8 +1532,9 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc)
   table->dynobj = NULL;
   /* Make sure can_refcount is extended to the width and signedness of
      init_refcount before we subtract one from it.  */
-  table->init_refcount = get_elf_backend_data (abfd)->can_refcount;
-  --table->init_refcount;
+  table->init_refcount.refcount = get_elf_backend_data (abfd)->can_refcount;
+  table->init_refcount.refcount -= 1;
+  table->init_offset.offset = -(bfd_vma) 1;
   /* The first dynamic symbol is a dummy.  */
   table->dynsymcount = 1;
   table->dynstr = NULL;
index aa359a1..a70f873 100644 (file)
@@ -2902,7 +2902,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
 
   /* Any syms created from now on start with -1 in
      got.refcount/offset and plt.refcount/offset.  */
-  elf_hash_table (info)->init_refcount = -1;
+  elf_hash_table (info)->init_refcount = elf_hash_table (info)->init_offset;
 
   /* The backend may have to create some sections regardless of whether
      we're dynamic or not.  */
@@ -3909,10 +3909,13 @@ elf_adjust_dynamic_symbol (h, data)
   bfd *dynobj;
   struct elf_backend_data *bed;
 
+  if (! is_elf_hash_table (eif->info))
+    return FALSE;
+
   if (h->root.type == bfd_link_hash_warning)
     {
-      h->plt.offset = (bfd_vma) -1;
-      h->got.offset = (bfd_vma) -1;
+      h->plt = elf_hash_table (eif->info)->init_offset;
+      h->got = elf_hash_table (eif->info)->init_offset;
 
       /* When warning symbols are created, they **replace** the "real"
         entry in the hash table, thus we never get to see the real
@@ -3924,9 +3927,6 @@ elf_adjust_dynamic_symbol (h, data)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (! is_elf_hash_table (eif->info))
-    return FALSE;
-
   /* Fix the symbol flags.  */
   if (! elf_fix_symbol_flags (h, eif))
     return FALSE;
@@ -3944,7 +3944,7 @@ elf_adjust_dynamic_symbol (h, data)
          || ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
              && (h->weakdef == NULL || h->weakdef->dynindx == -1))))
     {
-      h->plt.offset = (bfd_vma) -1;
+      h->plt = elf_hash_table (eif->info)->init_offset;
       return TRUE;
     }