long min_got_dynindx;
/* The greatest dynamic symbol table index corresponding to a symbol
with a GOT entry that is not referenced (e.g., a dynamic symbol
- with dynamic relocations pointing to it from non-primary
- GOTs). */
+ with dynamic relocations pointing to it from non-primary GOTs). */
long max_unref_got_dynindx;
/* The greatest dynamic symbol table index not corresponding to a
symbol without a GOT entry. */
const Elf_Internal_Rela *));
static bfd_boolean mips_elf_local_relocation_p
PARAMS ((bfd *, const Elf_Internal_Rela *, asection **, bfd_boolean));
-static bfd_vma mips_elf_sign_extend PARAMS ((bfd_vma, int));
static bfd_boolean mips_elf_overflow_p PARAMS ((bfd_vma, int));
static bfd_vma mips_elf_high PARAMS ((bfd_vma));
static bfd_vma mips_elf_higher PARAMS ((bfd_vma));
/* The name of the options section. */
#define MIPS_ELF_OPTIONS_SECTION_NAME(abfd) \
- (ABI_64_P (abfd) ? ".MIPS.options" : ".options")
+ (NEWABI_P (abfd) ? ".MIPS.options" : ".options")
/* The name of the stub section. */
#define MIPS_ELF_STUB_SECTION_NAME(abfd) \
- (ABI_64_P (abfd) ? ".MIPS.stubs" : ".stub")
+ (NEWABI_P (abfd) ? ".MIPS.stubs" : ".stub")
/* The size of an external REL relocation. */
#define MIPS_ELF_REL_SIZE(abfd) \
\f
bfd_reloc_status_type
_bfd_mips_elf_gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
- relocateable, data, gp)
+ relocatable, data, gp)
bfd *abfd;
asymbol *symbol;
arelent *reloc_entry;
asection *input_section;
- bfd_boolean relocateable;
+ bfd_boolean relocatable;
PTR data;
bfd_vma gp;
{
bfd_vma relocation;
- unsigned long insn;
- unsigned long val;
+ unsigned long insn = 0;
+ bfd_signed_vma val;
if (bfd_is_com_section (symbol->section))
relocation = 0;
if (reloc_entry->address > input_section->_cooked_size)
return bfd_reloc_outofrange;
- insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-
/* Set val to the offset into the section or symbol. */
- if (reloc_entry->howto->src_mask == 0)
- {
- /* This case occurs with the 64-bit MIPS ELF ABI. */
- val = reloc_entry->addend;
- }
- else
+ val = reloc_entry->addend;
+
+ if (reloc_entry->howto->partial_inplace)
{
- val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
- if (val & 0x8000)
- val -= 0x10000;
+ insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+ val += insn & 0xffff;
}
+ _bfd_mips_elf_sign_extend(val, 16);
+
/* Adjust val for the final section location and GP value. If we
- are producing relocateable output, we don't want to do this for
+ are producing relocatable output, we don't want to do this for
an external symbol. */
- if (! relocateable
+ if (! relocatable
|| (symbol->flags & BSF_SECTION_SYM) != 0)
val += relocation - gp;
- insn = (insn & ~0xffff) | (val & 0xffff);
- bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+ if (reloc_entry->howto->partial_inplace)
+ {
+ insn = (insn & ~0xffff) | (val & 0xffff);
+ bfd_put_32 (abfd, (bfd_vma) insn,
+ (bfd_byte *) data + reloc_entry->address);
+ }
+ else
+ reloc_entry->addend = val;
- if (relocateable)
+ if (relocatable)
reloc_entry->address += input_section->output_offset;
-
- else if ((long) val >= 0x8000 || (long) val < -0x8000)
+ else if (((val & ~0xffff) != ~0xffff) && ((val & ~0xffff) != 0))
return bfd_reloc_overflow;
return bfd_reloc_ok;
| SEC_LINKER_CREATED
| SEC_READONLY))
|| ! bfd_set_section_alignment (dynobj, sreloc,
- 4))
+ MIPS_ELF_LOG_FILE_ALIGN (dynobj)))
return NULL;
}
return sreloc;
if (abfd == NULL)
return 0;
-
+
sgot = mips_elf_got_section (abfd, TRUE);
if (sgot == NULL || mips_elf_section_data (sgot) == NULL)
return 0;
-
+
g = mips_elf_section_data (sgot)->u.got_info;
if (g == NULL || g->global_gotsym == NULL)
return 0;
-
+
return g->global_gotsym->dynindx;
}
if (g->bfd2got && ibfd)
{
struct mips_got_entry e, *p;
-
+
BFD_ASSERT (h->dynindx >= 0);
g = mips_elf_got_for_ibfd (g, ibfd);
if (!entry)
return MINUS_ONE;
-
+
index = entry->gotidx;
if (offsetp)
g = mips_elf_got_info (dynobj, &sgot);
gp = _bfd_get_gp_value (output_bfd)
+ mips_elf_adjust_gp (output_bfd, g, input_bfd);
-
+
return sgot->output_section->vma + sgot->output_offset + index - gp;
}
INSERT);
if (*loc)
return *loc;
-
+
entry.gotidx = MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno++;
*loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
if (! *loc)
return NULL;
-
+
memcpy (*loc, &entry, sizeof entry);
if (g->assigned_gotno >= g->local_gotno)
g = mips_elf_got_info (dynobj, NULL);
hsd.low = NULL;
- hsd.max_unref_got_dynindx =
+ hsd.max_unref_got_dynindx =
hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount
/* In the multi-got case, assigned_gotno of the master got_info
indicate the number of entries that aren't referenced in the
if (! *loc)
return FALSE;
-
+
entry.gotidx = -1;
memcpy (*loc, &entry, sizeof entry);
if (! *loc)
return FALSE;
-
+
memcpy (*loc, &entry, sizeof entry);
return TRUE;
struct mips_got_info *g;
struct mips_elf_bfd2got_hash bfdgot_entry, *bfdgot;
void **bfdgotp;
-
+
/* Find the got_info for this GOT entry's input bfd. Create one if
none exists. */
bfdgot_entry.bfd = entry->abfd;
entryp = htab_find_slot (g->got_entries, entry, INSERT);
if (*entryp != NULL)
return 1;
-
+
*entryp = entry;
if (entry->symndx >= 0 || entry->d.h->forced_local)
unsigned int lcount = bfd2got->g->local_gotno;
unsigned int gcount = bfd2got->g->global_gotno;
unsigned int maxcnt = arg->max_count;
-
+
/* If we don't have a primary GOT and this is not too big, use it as
a starting point for the primary GOT. */
if (! arg->primary && lcount + gcount <= maxcnt)
{
bfd2got->g->next = arg->current;
arg->current = bfd2got->g;
-
+
arg->current_count = lcount + gcount;
}
if (entry->d.h == h)
return 1;
-
+
entry->d.h = h;
/* If we can't find this entry with the new bfd hash, re-insert
/* We might want to decrement the global_gotno count, but it's
either too early or too late for that at this point. */
}
-
+
return 1;
}
BFD_ASSERT (g->next);
g = g->next;
-
+
return (g->local_gotno + g->global_gotno) * MIPS_ELF_GOT_SIZE (abfd);
}
{
struct mips_elf_bfd2got_hash *bfdgot;
void **bfdgotp;
-
+
bfdgot = (struct mips_elf_bfd2got_hash *)bfd_alloc
(abfd, sizeof (struct mips_elf_bfd2got_hash));
the cache. Also, knowing that every external symbol has a GOT
helps speed up the resolution of local symbols too, so GNU/Linux
follows IRIX's practice.
-
+
The number 2 is used by mips_elf_sort_hash_table_f to count
global GOT symbols that are unreferenced in the primary GOT, with
an initial dynamic index computed from gg->assigned_gotno, where
got->_raw_size = (gg->next->local_gotno
+ gg->next->global_gotno) * MIPS_ELF_GOT_SIZE (abfd);
-
+
return TRUE;
}
-
+
\f
/* Returns the first relocation of type r_type found, beginning with
RELOCATION. RELEND is one-past-the-end of the relocation table. */
\f
/* Sign-extend VALUE, which has the indicated number of BITS. */
-static bfd_vma
-mips_elf_sign_extend (value, bits)
+bfd_vma
+_bfd_mips_elf_sign_extend (value, bits)
bfd_vma value;
int bits;
{
s = bfd_make_section (abfd, ".got");
if (s == NULL
|| ! bfd_set_section_flags (abfd, s, flags)
- || ! bfd_set_section_alignment (abfd, s, 4))
+ || ! bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd)))
return FALSE;
/* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the
/* If this is a 32- or 64-bit call to a 16-bit function with a stub, we
need to redirect the call to the stub, unless we're already *in*
a stub. */
- if (r_type != R_MIPS16_26 && !info->relocateable
+ if (r_type != R_MIPS16_26 && !info->relocatable
&& ((h != NULL && h->fn_stub != NULL)
|| (local_p && elf_tdata (input_bfd)->local_stubs != NULL
&& elf_tdata (input_bfd)->local_stubs[r_symndx] != NULL))
}
/* If this is a 16-bit call to a 32- or 64-bit function with a stub, we
need to redirect the call to the stub. */
- else if (r_type == R_MIPS16_26 && !info->relocateable
+ else if (r_type == R_MIPS16_26 && !info->relocatable
&& h != NULL
&& (h->call_stub != NULL || h->call_fp_stub != NULL)
&& !target_is_16_bit_code_p)
/* Calls from 16-bit code to 32-bit code and vice versa require the
special jalx instruction. */
- *require_jalxp = (!info->relocateable
+ *require_jalxp = (!info->relocatable
&& (((r_type == R_MIPS16_26) && !target_is_16_bit_code_p)
|| ((r_type == R_MIPS_26) && target_is_16_bit_code_p)));
return bfd_reloc_continue;
case R_MIPS_16:
- value = symbol + mips_elf_sign_extend (addend, 16);
+ value = symbol + _bfd_mips_elf_sign_extend (addend, 16);
overflowed_p = mips_elf_overflow_p (value, 16);
break;
break;
case R_MIPS_GNU_REL16_S2:
- value = symbol + mips_elf_sign_extend (addend << 2, 18) - p;
+ value = symbol + _bfd_mips_elf_sign_extend (addend << 2, 18) - p;
overflowed_p = mips_elf_overflow_p (value, 18);
value = (value >> 2) & howto->dst_mask;
break;
if (local_p)
value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
else
- value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
+ value = (_bfd_mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
value &= howto->dst_mask;
break;
instruction. If the addend was separate, leave it alone,
otherwise we may lose significant bits. */
if (howto->partial_inplace)
- addend = mips_elf_sign_extend (addend, 16);
+ addend = _bfd_mips_elf_sign_extend (addend, 16);
value = symbol + addend - gp;
/* If the symbol was local, any earlier relocatable links will
have adjusted its addend with the gp offset, so compensate
break;
case R_MIPS_PC16:
- value = mips_elf_sign_extend (addend, 16) + symbol - p;
+ value = _bfd_mips_elf_sign_extend (addend, 16) + symbol - p;
overflowed_p = mips_elf_overflow_p (value, 16);
break;
JALX is the 5-bit value 00011. X is 0 for jal, 1 for jalx.
Note that the immediate value in the first word is swapped.
- When producing a relocateable object file, R_MIPS16_26 is
+ When producing a relocatable object file, R_MIPS16_26 is
handled mostly like R_MIPS_26. In particular, the addend is
stored as a straight 26-bit value in a 32-bit instruction.
(gas makes life simpler for itself by never adjusting a
where targ26-16 is sub1 followed by sub2 (i.e., the addend field A is
((sub1 << 16) | sub2)).
- When producing a relocateable object file, the calculation is
+ When producing a relocatable object file, the calculation is
(((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
When producing a fully linked file, the calculation is
let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff) */
- if (!info->relocateable)
+ if (!info->relocatable)
/* Shuffle the bits according to the formula above. */
value = (((value & 0x1f0000) << 5)
| ((value & 0x3e00000) >> 5)
/* We begin by assuming that the offset for the dynamic relocation
is the same as for the original relocation. We'll adjust this
later to reflect the correct output offsets. */
- if (elf_section_data (input_section)->sec_info_type != ELF_INFO_TYPE_STABS)
+ if (input_section->sec_info_type != ELF_INFO_TYPE_STABS)
{
outrel[1].r_offset = rel[1].r_offset;
outrel[2].r_offset = rel[2].r_offset;
/* Change alignments of some sections. */
s = bfd_get_section_by_name (abfd, ".hash");
if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
+ bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
s = bfd_get_section_by_name (abfd, ".dynsym");
if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
+ bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
s = bfd_get_section_by_name (abfd, ".dynstr");
if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
+ bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
s = bfd_get_section_by_name (abfd, ".reginfo");
if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
+ bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
s = bfd_get_section_by_name (abfd, ".dynamic");
if (s != NULL)
- bfd_set_section_alignment (abfd, s, 4);
+ bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
}
if (!info->shared)
asection *sreloc;
struct elf_backend_data *bed;
- if (info->relocateable)
+ if (info->relocatable)
return TRUE;
dynobj = elf_hash_table (info)->dynobj;
{
struct mips_elf_link_hash_entry *hmips =
(struct mips_elf_link_hash_entry *) h;
-
+
while (hmips->root.root.type == bfd_link_hash_indirect
|| hmips->root.root.type == bfd_link_hash_warning)
hmips = (struct mips_elf_link_hash_entry *)
hmips->root.root.u.i.link;
-
+
if ((hmips->root.root.type == bfd_link_hash_defined
|| hmips->root.root.type == bfd_link_hash_defweak)
&& hmips->root.root.u.def.section
/* We are not currently changing any sizes, so only one pass. */
*again = FALSE;
- if (link_info->relocateable)
+ if (link_info->relocatable)
return TRUE;
internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, (PTR) NULL,
while (h->root.root.type == bfd_link_hash_indirect
|| h->root.root.type == bfd_link_hash_warning)
h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
-
+
/* If a symbol is undefined, or if it may be overridden,
skip it. */
if (! ((h->root.root.type == bfd_link_hash_defined
/* Check that it's in range. */
if (sym_offset < -0x8000 || sym_offset >= 0x8000)
continue;
-
+
/* Get the section contents if we haven't done so already. */
if (contents == NULL)
{
}
return TRUE;
- relax_return:
+ relax_return:
if (free_contents != NULL)
free (free_contents);
return FALSE;
any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output
file. */
hmips = (struct mips_elf_link_hash_entry *) h;
- if (! info->relocateable
+ if (! info->relocatable
&& hmips->possibly_dynamic_relocs != 0
&& (h->root.type == bfd_link_hash_defweak
|| (h->elf_link_hash_flags
bfd_set_section_size (output_bfd, ri,
(bfd_size_type) sizeof (Elf32_External_RegInfo));
- if (! (info->relocateable
+ if (! (info->relocatable
|| ! mips_elf_hash_table (info)->mips16_stubs_seen))
mips_elf_link_hash_traverse (mips_elf_hash_table (info),
mips_elf_check_mips16_stubs,
if (dynobj == NULL)
/* Relocatable links don't have it. */
return TRUE;
-
+
g = mips_elf_got_info (dynobj, &s);
if (s == NULL)
return TRUE;
struct mips_got_info *g = gg;
struct mips_elf_set_global_got_offset_arg set_got_offset_arg;
unsigned int needed_relocs = 0;
-
+
if (gg->next)
{
set_got_offset_arg.value = MIPS_ELF_GOT_SIZE (output_bfd);
input_bfd, contents);
l &= lo16_howto->src_mask;
l <<= lo16_howto->rightshift;
- l = mips_elf_sign_extend (l, 16);
+ l = _bfd_mips_elf_sign_extend (l, 16);
addend <<= 16;
addend = rel->r_addend;
}
- if (info->relocateable)
+ if (info->relocatable)
{
Elf_Internal_Sym *sym;
unsigned long r_symndx;
they're against a section symbol, in which case we need
to adjust by the section offset, or unless they're GP
relative in which case we need to adjust by the amount
- that we're adjusting GP in this relocateable object. */
+ that we're adjusting GP in this relocatable object. */
if (! mips_elf_local_relocation_p (input_bfd, rel, local_sections,
FALSE))
e.abfd = output_bfd;
e.symndx = -1;
e.d.h = (struct mips_elf_link_hash_entry *)h;
-
+
if (info->shared
|| h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak)
h = (struct mips_elf_link_hash_entry *) entry;
if (h->forced_local)
return;
- h->forced_local = TRUE;
+ h->forced_local = force_local;
dynobj = elf_hash_table (info)->dynobj;
- if (dynobj != NULL)
+ if (dynobj != NULL && force_local)
{
got = mips_elf_got_section (dynobj, FALSE);
g = mips_elf_section_data (got)->u.got_info;
cookie->rel = cookie->rels;
cookie->relend = cookie->rels + o->reloc_count;
- for (i = 0, skip = 0; i < o->_raw_size; i ++)
+ for (i = 0, skip = 0; i < o->_raw_size / PDR_SIZE; i ++)
{
if (MNAME(abfd,_bfd_elf,reloc_symbol_deleted_p) (i * PDR_SIZE, cookie))
{
bfd_byte *
_bfd_elf_mips_get_relocated_section_contents (abfd, link_info, link_order,
- data, relocateable, symbols)
+ data, relocatable, symbols)
bfd *abfd;
struct bfd_link_info *link_info;
struct bfd_link_order *link_order;
bfd_byte *data;
- bfd_boolean relocateable;
+ bfd_boolean relocatable;
asymbol **symbols;
{
/* Get enough memory to hold the stuff */
{
/* bypass special_function call */
r = _bfd_mips_elf_gprel16_with_gp (input_bfd, sym, *parent,
- input_section, relocateable,
+ input_section, relocatable,
(PTR) data, gp);
goto skip_bfd_perform_relocation;
}
*parent,
(PTR) data,
input_section,
- relocateable ? abfd : (bfd *) NULL,
+ relocatable ? abfd : (bfd *) NULL,
&error_message);
skip_bfd_perform_relocation:
- if (relocateable)
+ if (relocatable)
{
asection *os = input_section->output_section;
scRData, scSData, scSBss, scBss
};
- /* If all the things we linked together were PIC, but we're
- producing an executable (rather than a shared object), then the
- resulting file is CPIC (i.e., it calls PIC code.) */
- if (!info->shared
- && !info->relocateable
- && elf_elfheader (abfd)->e_flags & EF_MIPS_PIC)
- {
- elf_elfheader (abfd)->e_flags &= ~EF_MIPS_PIC;
- elf_elfheader (abfd)->e_flags |= EF_MIPS_CPIC;
- }
-
/* We'd carefully arranged the dynamic symbol indices, and then the
generic size_dynamic_sections renumbered them out from under us.
Rather than trying somehow to prevent the renumbering, just do
elf_gp (abfd) = (h->u.def.value
+ h->u.def.section->output_section->vma
+ h->u.def.section->output_offset);
- else if (info->relocateable)
+ else if (info->relocatable)
{
bfd_vma lo = MINUS_ONE;
information describing how the small data area would
change depending upon the -G switch. These sections
not used in executables files. */
- if (! info->relocateable)
+ if (! info->relocatable)
{
for (p = o->link_order_head;
p != (struct bfd_link_order *) NULL;
ok = TRUE;
- if ((new_flags & EF_MIPS_PIC) != (old_flags & EF_MIPS_PIC))
+ if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)
+ != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0))
{
- new_flags &= ~EF_MIPS_PIC;
- old_flags &= ~EF_MIPS_PIC;
(*_bfd_error_handler)
- (_("%s: linking PIC files with non-PIC files"),
+ (_("%s: warning: linking PIC files with non-PIC files"),
bfd_archive_filename (ibfd));
- ok = FALSE;
+ ok = TRUE;
}
- if ((new_flags & EF_MIPS_CPIC) != (old_flags & EF_MIPS_CPIC))
- {
- new_flags &= ~EF_MIPS_CPIC;
- old_flags &= ~EF_MIPS_CPIC;
- (*_bfd_error_handler)
- (_("%s: linking abicalls files with non-abicalls files"),
- bfd_archive_filename (ibfd));
- ok = FALSE;
- }
+ if (new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC))
+ elf_elfheader (obfd)->e_flags |= EF_MIPS_CPIC;
+ if (! (new_flags & EF_MIPS_PIC))
+ elf_elfheader (obfd)->e_flags &= ~EF_MIPS_PIC;
+
+ new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
+ old_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC);
/* Compare the ISAs. */
if (mips_32bit_flags_p (old_flags) != mips_32bit_flags_p (new_flags))