summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2003-02-04 12:49:57 +0000
committerAlan Modra <amodra@bigpond.net.au>2003-02-04 12:49:57 +0000
commitc50be2b5797edde9703c579fe82ecbf61f0d1c8f (patch)
tree2cf97c447de8a3a6b0fdd52f297fd04b2a47aa78
parent92c4da53e196713256db6d6133bfc775a40a063b (diff)
downloadgdb-c50be2b5797edde9703c579fe82ecbf61f0d1c8f.tar.gz
* 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.
-rw-r--r--bfd/ChangeLog22
-rw-r--r--bfd/elf-bfd.h48
-rw-r--r--bfd/elf.c41
-rw-r--r--bfd/elflink.h14
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,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.
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;
}