From 5cab59f6227cb9ef3e5ed2a5bf9df5d3836645b2 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 4 Feb 2003 12:49:57 +0000 Subject: [PATCH] * 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 ): 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 | 22 ++++++++++++++++++++++ bfd/elf-bfd.h | 48 +++++++++++++++++++++++++++--------------------- bfd/elf.c | 41 ++++++++++++++++++++++++----------------- bfd/elflink.h | 14 +++++++------- 4 files changed, 80 insertions(+), 45 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 21d22b33cd4..2077794a138 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,25 @@ +2003-02-04 Alan Modra + + * 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 ): 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 * elf-bfd.h (enum elf_link_info_type): Remove. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 8c401b5be8a..2e5587cf798 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -80,6 +80,8 @@ typedef struct } elf_symbol_type; 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 *)); diff --git a/bfd/elf.c b/bfd/elf.c index c4c6487b226..be0025d0a4d 100644 --- 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; diff --git a/bfd/elflink.h b/bfd/elflink.h index aa359a18eb9..a70f873af6a 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -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; } -- 2.30.2