struct bfd_elf_section_data elf;
union
{
- struct mips_got_info *got_info;
bfd_byte *tdata;
} u;
};
asection *sgotplt;
asection *splt;
asection *sstubs;
+ asection *sgot;
+ /* The master GOT information. */
+ struct mips_got_info *got_info;
/* The size of the PLT header in bytes (VxWorks only). */
bfd_vma plt_header_size;
/* The size of a PLT entry in bytes (VxWorks only). */
#define rpdNil ((pRPDR) 0)
\f
static struct mips_got_entry *mips_elf_create_local_got_entry
- (bfd *, struct bfd_link_info *, bfd *, struct mips_got_info *, asection *,
- bfd_vma, unsigned long, struct mips_elf_link_hash_entry *, int);
+ (bfd *, struct bfd_link_info *, bfd *, bfd_vma, unsigned long,
+ struct mips_elf_link_hash_entry *, int);
static bfd_boolean mips_elf_sort_hash_table_f
(struct mips_elf_link_hash_entry *, void *);
static bfd_vma mips_elf_high
return sreloc;
}
-/* Returns the GOT section for ABFD. */
+/* Returns the GOT section, if it hasn't been excluded. */
static asection *
-mips_elf_got_section (bfd *abfd, bfd_boolean maybe_excluded)
-{
- asection *sgot = bfd_get_section_by_name (abfd, ".got");
- if (sgot == NULL
- || (! maybe_excluded && (sgot->flags & SEC_EXCLUDE) != 0))
- return NULL;
- return sgot;
-}
-
-/* Returns the GOT information associated with the link indicated by
- INFO. If SGOTP is non-NULL, it is filled in with the GOT
- section. */
-
-static struct mips_got_info *
-mips_elf_got_info (bfd *abfd, asection **sgotp)
+mips_elf_got_section (struct bfd_link_info *info)
{
- asection *sgot;
- struct mips_got_info *g;
-
- sgot = mips_elf_got_section (abfd, TRUE);
- BFD_ASSERT (sgot != NULL);
- BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
- g = mips_elf_section_data (sgot)->u.got_info;
- BFD_ASSERT (g != NULL);
-
- if (sgotp)
- *sgotp = (sgot->flags & SEC_EXCLUDE) == 0 ? sgot : NULL;
+ struct mips_elf_link_hash_table *htab;
- return g;
+ htab = mips_elf_hash_table (info);
+ if (htab->sgot == NULL || (htab->sgot->flags & SEC_EXCLUDE) != 0)
+ return NULL;
+ return htab->sgot;
}
/* Count the number of relocations needed for a TLS GOT entry, with
int indx;
asection *sreloc, *sgot;
bfd_vma offset, offset2;
- bfd *dynobj;
bfd_boolean need_relocs = FALSE;
- dynobj = elf_hash_table (info)->dynobj;
- sgot = mips_elf_got_section (dynobj, FALSE);
+ sgot = mips_elf_got_section (info);
indx = 0;
if (h != NULL)
bfd_vma value, unsigned long r_symndx,
struct mips_elf_link_hash_entry *h, int r_type)
{
- asection *sgot;
- struct mips_got_info *g;
+ struct mips_elf_link_hash_table *htab;
struct mips_got_entry *entry;
- g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
-
- entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot,
- value, r_symndx, h, r_type);
+ htab = mips_elf_hash_table (info);
+ entry = mips_elf_create_local_got_entry (abfd, info, ibfd, value,
+ r_symndx, h, r_type);
if (!entry)
return MINUS_ONE;
if (TLS_RELOC_P (r_type))
{
- if (entry->symndx == -1 && g->next == NULL)
+ if (entry->symndx == -1 && htab->got_info->next == NULL)
/* A type (3) entry in the single-GOT case. We use the symbol's
hash table entry to track the index. */
return mips_tls_got_index (abfd, h->tls_got_offset, &h->tls_type,
mips_elf_global_got_index (bfd *abfd, bfd *ibfd, struct elf_link_hash_entry *h,
int r_type, struct bfd_link_info *info)
{
+ struct mips_elf_link_hash_table *htab;
bfd_vma index;
- asection *sgot;
struct mips_got_info *g, *gg;
long global_got_dynindx = 0;
- gg = g = mips_elf_got_info (abfd, &sgot);
+ htab = mips_elf_hash_table (info);
+ gg = g = htab->got_info;
if (g->bfd2got && ibfd)
{
struct mips_got_entry e, *p;
index = ((h->dynindx - global_got_dynindx + g->local_gotno)
* MIPS_ELF_GOT_SIZE (abfd));
}
- BFD_ASSERT (index < sgot->size);
+ BFD_ASSERT (index < htab->sgot->size);
return index;
}
mips_elf_got_page (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
bfd_vma value, bfd_vma *offsetp)
{
- asection *sgot;
- struct mips_got_info *g;
bfd_vma page, index;
struct mips_got_entry *entry;
- g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
-
page = (value + 0x8000) & ~(bfd_vma) 0xffff;
- entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot,
- page, 0, NULL, R_MIPS_GOT_PAGE);
+ entry = mips_elf_create_local_got_entry (abfd, info, ibfd, page, 0,
+ NULL, R_MIPS_GOT_PAGE);
if (!entry)
return MINUS_ONE;
mips_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info,
bfd_vma value, bfd_boolean external)
{
- asection *sgot;
- struct mips_got_info *g;
struct mips_got_entry *entry;
/* GOT16 relocations against local symbols are followed by a LO16
if (! external)
value = mips_elf_high (value) << 16;
- g = mips_elf_got_info (elf_hash_table (info)->dynobj, &sgot);
-
/* It doesn't matter whether the original relocation was R_MIPS_GOT16,
R_MIPS16_GOT16, R_MIPS_CALL16, etc. The format of the entry is the
same in all cases. */
- entry = mips_elf_create_local_got_entry (abfd, info, ibfd, g, sgot,
- value, 0, NULL, R_MIPS_GOT16);
+ entry = mips_elf_create_local_got_entry (abfd, info, ibfd, value, 0,
+ NULL, R_MIPS_GOT16);
if (entry)
return entry->gotidx;
else
in the GOT. */
static bfd_vma
-mips_elf_got_offset_from_index (bfd *dynobj, bfd *output_bfd,
+mips_elf_got_offset_from_index (struct bfd_link_info *info, bfd *output_bfd,
bfd *input_bfd, bfd_vma index)
{
+ struct mips_elf_link_hash_table *htab;
asection *sgot;
bfd_vma gp;
- struct mips_got_info *g;
- g = mips_elf_got_info (dynobj, &sgot);
+ htab = mips_elf_hash_table (info);
+ sgot = htab->sgot;
gp = _bfd_get_gp_value (output_bfd)
- + mips_elf_adjust_gp (output_bfd, g, input_bfd);
+ + mips_elf_adjust_gp (output_bfd, htab->got_info, input_bfd);
return sgot->output_section->vma + sgot->output_offset + index - gp;
}
static struct mips_got_entry *
mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
- bfd *ibfd, struct mips_got_info *gg,
- asection *sgot, bfd_vma value,
+ bfd *ibfd, bfd_vma value,
unsigned long r_symndx,
struct mips_elf_link_hash_entry *h,
int r_type)
entry.d.address = value;
entry.tls_type = 0;
- g = mips_elf_got_for_ibfd (gg, ibfd);
+ g = mips_elf_got_for_ibfd (htab->got_info, ibfd);
if (g == NULL)
{
- g = mips_elf_got_for_ibfd (gg, abfd);
+ g = mips_elf_got_for_ibfd (htab->got_info, abfd);
BFD_ASSERT (g != NULL);
}
}
MIPS_ELF_PUT_WORD (abfd, value,
- (sgot->contents + entry.gotidx));
+ (htab->sgot->contents + entry.gotidx));
/* These GOT entries need a dynamic relocation on VxWorks. */
if (htab->is_vxworks)
bfd_vma got_address;
s = mips_elf_rel_dyn_section (info, FALSE);
- got_address = (sgot->output_section->vma
- + sgot->output_offset
+ got_address = (htab->sgot->output_section->vma
+ + htab->sgot->output_offset
+ entry.gotidx);
loc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela));
static bfd_boolean
mips_elf_sort_hash_table (struct bfd_link_info *info, unsigned long max_local)
{
+ struct mips_elf_link_hash_table *htab;
struct mips_elf_hash_sort_data hsd;
struct mips_got_info *g;
- bfd *dynobj;
-
- dynobj = elf_hash_table (info)->dynobj;
- g = mips_elf_got_info (dynobj, NULL);
+ htab = mips_elf_hash_table (info);
+ g = htab->got_info;
hsd.low = NULL;
hsd.max_unref_got_dynindx =
static bfd_boolean
mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
bfd *abfd, struct bfd_link_info *info,
- struct mips_got_info *g,
unsigned char tls_flag)
{
+ struct mips_elf_link_hash_table *htab;
struct mips_got_entry entry, **loc;
+ struct mips_got_info *g;
+
+ htab = mips_elf_hash_table (info);
/* A global symbol in the GOT must also be in the dynamic symbol
table. */
}
/* Make sure we have a GOT to put this entry into. */
+ g = htab->got_info;
BFD_ASSERT (g != NULL);
entry.abfd = abfd;
static bfd_boolean
mips_elf_record_local_got_symbol (bfd *abfd, long symndx, bfd_vma addend,
- struct mips_got_info *g,
+ struct bfd_link_info *info,
unsigned char tls_flag)
{
+ struct mips_elf_link_hash_table *htab;
+ struct mips_got_info *g;
struct mips_got_entry entry, **loc;
+ htab = mips_elf_hash_table (info);
+ g = htab->got_info;
+ BFD_ASSERT (g != NULL);
+
entry.abfd = abfd;
entry.symndx = symndx;
entry.d.addend = addend;
}
/* Record that ABFD has a page relocation against symbol SYMNDX and
- that ADDEND is the addend for that relocation. G is the GOT
- information. This function creates an upper bound on the number of
- GOT slots required; no attempt is made to combine references to
- non-overridable global symbols across multiple input files. */
+ that ADDEND is the addend for that relocation.
+
+ This function creates an upper bound on the number of GOT slots
+ required; no attempt is made to combine references to non-overridable
+ global symbols across multiple input files. */
static bfd_boolean
-mips_elf_record_got_page_entry (bfd *abfd, long symndx, bfd_signed_vma addend,
- struct mips_got_info *g)
+mips_elf_record_got_page_entry (struct bfd_link_info *info, bfd *abfd,
+ long symndx, bfd_signed_vma addend)
{
+ struct mips_elf_link_hash_table *htab;
+ struct mips_got_info *g;
struct mips_got_page_entry lookup, *entry;
struct mips_got_page_range **range_ptr, *range;
bfd_vma old_pages, new_pages;
void **loc;
+ htab = mips_elf_hash_table (info);
+ g = htab->got_info;
+ BFD_ASSERT (g != NULL);
+
/* Find the mips_got_page_entry hash table entry for this symbol. */
lookup.abfd = abfd;
lookup.symndx = symndx;
static bfd_boolean
mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
- struct mips_got_info *g, asection *got,
- bfd_size_type pages)
+ asection *got, bfd_size_type pages)
{
+ struct mips_elf_link_hash_table *htab;
struct mips_elf_got_per_bfd_arg got_per_bfd_arg;
struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
- struct mips_got_info *gg;
+ struct mips_got_info *g, *gg;
unsigned int assign;
+ htab = mips_elf_hash_table (info);
+ g = htab->got_info;
g->bfd2got = htab_try_create (1, mips_elf_bfd2got_entry_hash,
mips_elf_bfd2got_entry_eq, NULL);
if (g->bfd2got == NULL)
htab = mips_elf_hash_table (info);
/* This function may be called more than once. */
- s = mips_elf_got_section (abfd, TRUE);
+ s = htab->sgot;
if (s)
{
if (! maybe_exclude)
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, 4))
return FALSE;
+ htab->sgot = s;
/* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the
linker script because we don't want to define the symbol if we
mips_got_page_entry_eq, NULL);
if (g->got_page_entries == NULL)
return FALSE;
- mips_elf_section_data (s)->u.got_info = g;
+ htab->got_info = g;
mips_elf_section_data (s)->elf.this_hdr.sh_flags
|= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
gp0 = _bfd_get_gp_value (input_bfd);
gp = _bfd_get_gp_value (abfd);
if (dynobj)
- gp += mips_elf_adjust_gp (abfd, mips_elf_got_info (dynobj, NULL),
- input_bfd);
+ gp += mips_elf_adjust_gp (abfd, htab->got_info, input_bfd);
if (gnu_local_gp_p)
symbol = gp;
|| (info->shared
&& (info->symbolic || h->root.forced_local)
&& h->root.def_regular)))
- {
- /* This is a static link or a -Bsymbolic link. The
- symbol is defined locally, or was forced to be local.
- We must initialize this entry in the GOT. */
- asection *sgot = mips_elf_got_section (dynobj, FALSE);
- MIPS_ELF_PUT_WORD (dynobj, symbol, sgot->contents + g);
- }
+ /* This is a static link or a -Bsymbolic link. The
+ symbol is defined locally, or was forced to be local.
+ We must initialize this entry in the GOT. */
+ MIPS_ELF_PUT_WORD (dynobj, symbol, htab->sgot->contents + g);
}
}
else if (!htab->is_vxworks
}
/* Convert GOT indices to actual offsets. */
- g = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, g);
+ g = mips_elf_got_offset_from_index (info, abfd, input_bfd, g);
break;
}
if (value == MINUS_ONE)
return bfd_reloc_outofrange;
value
- = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, value);
+ = mips_elf_got_offset_from_index (info, abfd, input_bfd, value);
overflowed_p = mips_elf_overflow_p (value, 16);
break;
}
value = mips_elf_got_page (abfd, input_bfd, info, symbol + addend, NULL);
if (value == MINUS_ONE)
return bfd_reloc_outofrange;
- value = mips_elf_got_offset_from_index (dynobj, abfd, input_bfd, value);
+ value = mips_elf_got_offset_from_index (info, abfd, input_bfd, value);
overflowed_p = mips_elf_overflow_p (value, 16);
break;
bfd *dynobj;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
- struct mips_got_info *g;
size_t extsymoff;
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
- asection *sgot;
asection *sreloc;
const struct elf_backend_data *bed;
struct mips_elf_link_hash_table *htab;
}
}
- if (dynobj == NULL)
- {
- sgot = NULL;
- g = NULL;
- }
- else
- {
- sgot = mips_elf_got_section (dynobj, FALSE);
- if (sgot == NULL)
- g = NULL;
- else
- {
- BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
- g = mips_elf_section_data (sgot)->u.got_info;
- BFD_ASSERT (g != NULL);
- }
- }
-
sreloc = NULL;
contents = NULL;
for (rel = relocs; rel < rel_end; ++rel)
}
/* Some relocs require a global offset table. */
- if (dynobj == NULL || sgot == NULL)
+ if (dynobj == NULL || htab->sgot == NULL)
{
switch (r_type)
{
elf_hash_table (info)->dynobj = dynobj = abfd;
if (! mips_elf_create_got_section (dynobj, info, FALSE))
return FALSE;
- g = mips_elf_got_info (dynobj, &sgot);
if (htab->is_vxworks && !info->shared)
{
(*_bfd_error_handler)
always evaluate to "G". We don't count R_MIPS_GOT_HI16, or
R_MIPS_CALL_HI16 because these are always followed by an
R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16. */
- if (! mips_elf_record_local_got_symbol (abfd, r_symndx,
- rel->r_addend, g, 0))
+ if (!mips_elf_record_local_got_symbol (abfd, r_symndx,
+ rel->r_addend, info, 0))
return FALSE;
}
entry, which will be allocated by adjust_dynamic_symbol.
Otherwise, this symbol requires a global GOT entry. */
if ((!htab->is_vxworks || h->forced_local)
- && !mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
+ && !mips_elf_record_global_got_symbol (h, abfd, info, 0))
return FALSE;
/* We need a stub, not a plt entry for the undefined
}
else
addend = rel->r_addend;
- if (!mips_elf_record_got_page_entry (abfd, r_symndx, addend, g))
+ if (!mips_elf_record_got_page_entry (info, abfd, r_symndx,
+ addend))
return FALSE;
break;
}
/* Fall through. */
case R_MIPS_GOT_DISP:
- if (h && ! mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
+ if (h && !mips_elf_record_global_got_symbol (h, abfd, info, 0))
return FALSE;
break;
(struct mips_elf_link_hash_entry *) h;
hmips->tls_type |= flag;
- if (h && ! mips_elf_record_global_got_symbol (h, abfd, info, g, flag))
+ if (h && !mips_elf_record_global_got_symbol (h, abfd,
+ info, flag))
return FALSE;
}
else
{
BFD_ASSERT (flag == GOT_TLS_LDM || r_symndx != 0);
- if (! mips_elf_record_local_got_symbol (abfd, r_symndx,
- rel->r_addend, g, flag))
+ if (!mips_elf_record_local_got_symbol (abfd, r_symndx,
+ rel->r_addend,
+ info, flag))
return FALSE;
}
}
elf_hash_table (info)->dynobj = dynobj = abfd;
if (! mips_elf_create_got_section (dynobj, info, TRUE))
return FALSE;
- g = mips_elf_got_info (dynobj, &sgot);
- if (! mips_elf_record_global_got_symbol (h, abfd, info, g, 0))
+ if (!mips_elf_record_global_got_symbol (h, abfd, info, 0))
return FALSE;
}
}
{
asection *ri;
- bfd *dynobj;
asection *s;
struct mips_got_info *g;
int i;
mips_elf_link_hash_traverse (mips_elf_hash_table (info),
mips_elf_check_mips16_stubs, info);
- dynobj = elf_hash_table (info)->dynobj;
- if (dynobj == NULL)
- /* Relocatable links don't have it. */
- return TRUE;
-
- g = mips_elf_got_info (dynobj, &s);
+ s = htab->sgot;
if (s == NULL)
return TRUE;
+ g = htab->got_info;
+
/* Calculate the total loadable size of the output. That
will give us the maximum number of GOT_PAGE entries
required. */
dynamic loader. */
if (!htab->is_vxworks && s->size > MIPS_ELF_GOT_MAX_SIZE (info))
{
- if (! mips_elf_multi_got (output_bfd, info, g, s, page_gotno))
+ if (!mips_elf_multi_got (output_bfd, info, s, page_gotno))
return FALSE;
}
else
if (info->shared)
{
/* Allocate relocations for all but the reserved entries. */
- struct mips_got_info *g;
unsigned int count;
- g = mips_elf_got_info (dynobj, NULL);
- count = (g->global_gotno
- + g->local_gotno
+ count = (htab->got_info->global_gotno
+ + htab->got_info->local_gotno
- MIPS_RESERVED_GOTNO (info));
mips_elf_allocate_dynamic_relocations (dynobj, info, count);
}
most of the work, but some symbols may have been mapped
to versions that we must now resolve in the got_entries
hash tables. */
- struct mips_got_info *gg = mips_elf_got_info (dynobj, NULL);
+ struct mips_got_info *gg = htab->got_info;
struct mips_got_info *g = gg;
struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
unsigned int needed_relocs = 0;
BFD_ASSERT (h->dynindx != -1
|| h->forced_local);
- sgot = mips_elf_got_section (dynobj, FALSE);
+ sgot = mips_elf_got_section (info);
BFD_ASSERT (sgot != NULL);
- BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
- g = mips_elf_section_data (sgot)->u.got_info;
+ g = htab->got_info;
BFD_ASSERT (g != NULL);
/* Run through the global symbol table, creating GOT entries for all
BFD_ASSERT (h->dynindx != -1 || h->forced_local);
- sgot = mips_elf_got_section (dynobj, FALSE);
+ sgot = mips_elf_got_section (info);
BFD_ASSERT (sgot != NULL);
- BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
- g = mips_elf_section_data (sgot)->u.got_info;
+ g = htab->got_info;
BFD_ASSERT (g != NULL);
/* See if this symbol has an entry in the GOT. */
sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
- sgot = mips_elf_got_section (dynobj, FALSE);
+ sgot = mips_elf_got_section (info);
if (sgot == NULL)
gg = g = NULL;
else
{
- BFD_ASSERT (mips_elf_section_data (sgot) != NULL);
- gg = mips_elf_section_data (sgot)->u.got_info;
- BFD_ASSERT (gg != NULL);
+ gg = htab->got_info;
g = mips_elf_got_for_ibfd (gg, output_bfd);
BFD_ASSERT (g != NULL);
}
bfd_boolean force_local)
{
bfd *dynobj;
- asection *got;
struct mips_got_info *g;
struct mips_elf_link_hash_entry *h;
struct mips_elf_link_hash_table *htab;
dynobj = elf_hash_table (info)->dynobj;
htab = mips_elf_hash_table (info);
- if (dynobj != NULL && force_local && h->root.type != STT_TLS
- && (got = mips_elf_got_section (dynobj, TRUE)) != NULL
- && (g = mips_elf_section_data (got)->u.got_info) != NULL)
+ if (dynobj != NULL
+ && force_local
+ && h->root.type != STT_TLS
+ && htab->got_info != NULL)
{
+ g = htab->got_info;
if (g->next)
{
struct mips_got_entry e;
/* The symbol is only used in call relocations, so we'll
have assumed it only needs a .got.plt entry. Increase
the size of .got accordingly. */
- got->size += MIPS_ELF_GOT_SIZE (dynobj);
+ htab->sgot->size += MIPS_ELF_GOT_SIZE (dynobj);
}
}
ret->sgotplt = NULL;
ret->splt = NULL;
ret->sstubs = NULL;
+ ret->sgot = NULL;
+ ret->got_info = NULL;
ret->plt_header_size = 0;
ret->plt_entry_size = 0;
ret->function_stub_size = 0;
htab = mips_elf_hash_table (info);
if (elf_hash_table (info)->dynamic_sections_created)
{
- bfd *dynobj;
- asection *got;
struct mips_got_info *g;
bfd_size_type dynsecsymcount;
return FALSE;
/* Make sure we didn't grow the global .got region. */
- dynobj = elf_hash_table (info)->dynobj;
- got = mips_elf_got_section (dynobj, FALSE);
- g = mips_elf_section_data (got)->u.got_info;
-
+ g = htab->got_info;
if (g->global_gotsym != NULL)
BFD_ASSERT ((elf_hash_table (info)->dynsymcount
- g->global_gotsym->dynindx)