mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-26 05:20:30 +00:00
* elf32-mips.c (struct mips_elf_link_hash_entry): Add
mips_32_relocs field. (mips_elf_link_hash_newfunc): Initialize mips_32_relocs field. (mips_elf_relocate_section): Copy R_MIPS_REL32 and R_MIPS_32 relocs against a global symbol which is not defined in a regular file. (mips_elf_check_relocs): For a R_MIPS_REL32 or R_MIPS_32 reloc against a global symbol, increment mips_32_relocs. (mips_elf_adjust_dynamic_symbol): If mips_32_relocs is set, and the symbol is not defined in a regular file, make room in the .rel.dyn section.
This commit is contained in:
parent
ec7d9f3d3c
commit
abec70b998
@ -1,3 +1,17 @@
|
||||
Mon Apr 29 13:15:17 1996 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* elf32-mips.c (struct mips_elf_link_hash_entry): Add
|
||||
mips_32_relocs field.
|
||||
(mips_elf_link_hash_newfunc): Initialize mips_32_relocs field.
|
||||
(mips_elf_relocate_section): Copy R_MIPS_REL32 and R_MIPS_32
|
||||
relocs against a global symbol which is not defined in a regular
|
||||
file.
|
||||
(mips_elf_check_relocs): For a R_MIPS_REL32 or R_MIPS_32 reloc
|
||||
against a global symbol, increment mips_32_relocs.
|
||||
(mips_elf_adjust_dynamic_symbol): If mips_32_relocs is set, and
|
||||
the symbol is not defined in a regular file, make room in the
|
||||
.rel.dyn section.
|
||||
|
||||
Fri Apr 26 18:00:37 1996 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* ecoff.c (ecoff_compute_section_file_positions): Track the real
|
||||
|
297
bfd/elf32-mips.c
297
bfd/elf32-mips.c
@ -154,7 +154,7 @@ static boolean mips_elf_add_symbol_hook
|
||||
PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
|
||||
const char **, flagword *, asection **, bfd_vma *));
|
||||
static bfd_reloc_status_type mips_elf_final_gp
|
||||
PARAMS ((bfd *, asymbol *, boolean, char **));
|
||||
PARAMS ((bfd *, asymbol *, boolean, char **, bfd_vma *));
|
||||
static bfd_byte *elf32_mips_get_relocated_section_contents
|
||||
PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
|
||||
bfd_byte *, boolean, asymbol **));
|
||||
@ -720,10 +720,21 @@ static reloc_howto_type elf_mips_howto_table[] =
|
||||
with a R_MIPS_LO16 reloc, because there is a carry from the LO16 to
|
||||
the HI16. Here we just save the information we need; we do the
|
||||
actual relocation when we see the LO16. MIPS ELF requires that the
|
||||
LO16 immediately follow the HI16, so this ought to work. */
|
||||
LO16 immediately follow the HI16. As a GNU extension, we permit an
|
||||
arbitrary number of HI16 relocs to be associated with a single LO16
|
||||
reloc. This extension permits gcc to output the HI and LO relocs
|
||||
itself. */
|
||||
|
||||
static bfd_byte *mips_hi16_addr;
|
||||
static bfd_vma mips_hi16_addend;
|
||||
struct mips_hi16
|
||||
{
|
||||
struct mips_hi16 *next;
|
||||
bfd_byte *addr;
|
||||
bfd_vma addend;
|
||||
};
|
||||
|
||||
/* FIXME: This should not be a static variable. */
|
||||
|
||||
static struct mips_hi16 *mips_hi16_list;
|
||||
|
||||
static bfd_reloc_status_type
|
||||
mips_elf_hi16_reloc (abfd,
|
||||
@ -743,6 +754,7 @@ mips_elf_hi16_reloc (abfd,
|
||||
{
|
||||
bfd_reloc_status_type ret;
|
||||
bfd_vma relocation;
|
||||
struct mips_hi16 *n;
|
||||
|
||||
/* If we're relocating, and this an external symbol, we don't want
|
||||
to change anything. */
|
||||
@ -759,6 +771,7 @@ mips_elf_hi16_reloc (abfd,
|
||||
if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
|
||||
{
|
||||
boolean relocateable;
|
||||
bfd_vma gp;
|
||||
|
||||
if (ret == bfd_reloc_undefined)
|
||||
abort ();
|
||||
@ -772,11 +785,11 @@ mips_elf_hi16_reloc (abfd,
|
||||
}
|
||||
|
||||
ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
|
||||
error_message);
|
||||
error_message, &gp);
|
||||
if (ret != bfd_reloc_ok)
|
||||
return ret;
|
||||
|
||||
relocation = _bfd_get_gp_value (output_bfd) - reloc_entry->address;
|
||||
relocation = gp - reloc_entry->address;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -798,8 +811,13 @@ mips_elf_hi16_reloc (abfd,
|
||||
return bfd_reloc_outofrange;
|
||||
|
||||
/* Save the information, and let LO16 do the actual relocation. */
|
||||
mips_hi16_addr = (bfd_byte *) data + reloc_entry->address;
|
||||
mips_hi16_addend = relocation;
|
||||
n = (struct mips_hi16 *) bfd_malloc (sizeof *n);
|
||||
if (n == NULL)
|
||||
return bfd_reloc_outofrange;
|
||||
n->addr = (bfd_byte *) data + reloc_entry->address;
|
||||
n->addend = relocation;
|
||||
n->next = mips_hi16_list;
|
||||
mips_hi16_list = n;
|
||||
|
||||
if (output_bfd != (bfd *) NULL)
|
||||
reloc_entry->address += input_section->output_offset;
|
||||
@ -829,56 +847,67 @@ mips_elf_lo16_reloc (abfd,
|
||||
{
|
||||
arelent gp_disp_relent;
|
||||
|
||||
if (mips_hi16_addr != (bfd_byte *) NULL)
|
||||
if (mips_hi16_list != NULL)
|
||||
{
|
||||
unsigned long insn;
|
||||
unsigned long val;
|
||||
unsigned long vallo;
|
||||
struct mips_hi16 *l;
|
||||
|
||||
/* Do the HI16 relocation. Note that we actually don't need to
|
||||
know anything about the LO16 itself, except where to find the
|
||||
low 16 bits of the addend needed by the LO16. */
|
||||
insn = bfd_get_32 (abfd, mips_hi16_addr);
|
||||
vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
|
||||
& 0xffff);
|
||||
val = ((insn & 0xffff) << 16) + vallo;
|
||||
val += mips_hi16_addend;
|
||||
|
||||
/* The low order 16 bits are always treated as a signed value.
|
||||
Therefore, a negative value in the low order bits requires an
|
||||
adjustment in the high order bits. We need to make this
|
||||
adjustment in two ways: once for the bits we took from the
|
||||
data, and once for the bits we are putting back in to the
|
||||
data. */
|
||||
if ((vallo & 0x8000) != 0)
|
||||
val -= 0x10000;
|
||||
if ((val & 0x8000) != 0)
|
||||
val += 0x10000;
|
||||
|
||||
insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
|
||||
bfd_put_32 (abfd, insn, mips_hi16_addr);
|
||||
|
||||
mips_hi16_addr = (bfd_byte *) NULL;
|
||||
|
||||
if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
|
||||
l = mips_hi16_list;
|
||||
while (l != NULL)
|
||||
{
|
||||
gp_disp_relent = *reloc_entry;
|
||||
reloc_entry = &gp_disp_relent;
|
||||
reloc_entry->addend = mips_hi16_addend;
|
||||
unsigned long insn;
|
||||
unsigned long val;
|
||||
unsigned long vallo;
|
||||
struct mips_hi16 *next;
|
||||
|
||||
/* Do the HI16 relocation. Note that we actually don't need
|
||||
to know anything about the LO16 itself, except where to
|
||||
find the low 16 bits of the addend needed by the LO16. */
|
||||
insn = bfd_get_32 (abfd, l->addr);
|
||||
vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
|
||||
& 0xffff);
|
||||
val = ((insn & 0xffff) << 16) + vallo;
|
||||
val += l->addend;
|
||||
|
||||
/* The low order 16 bits are always treated as a signed
|
||||
value. Therefore, a negative value in the low order bits
|
||||
requires an adjustment in the high order bits. We need
|
||||
to make this adjustment in two ways: once for the bits we
|
||||
took from the data, and once for the bits we are putting
|
||||
back in to the data. */
|
||||
if ((vallo & 0x8000) != 0)
|
||||
val -= 0x10000;
|
||||
if ((val & 0x8000) != 0)
|
||||
val += 0x10000;
|
||||
|
||||
insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
|
||||
bfd_put_32 (abfd, insn, l->addr);
|
||||
|
||||
if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
|
||||
{
|
||||
gp_disp_relent = *reloc_entry;
|
||||
reloc_entry = &gp_disp_relent;
|
||||
reloc_entry->addend = l->addend;
|
||||
}
|
||||
|
||||
next = l->next;
|
||||
free (l);
|
||||
l = next;
|
||||
}
|
||||
|
||||
mips_hi16_list = NULL;
|
||||
}
|
||||
else if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
|
||||
{
|
||||
bfd_reloc_status_type ret;
|
||||
bfd_vma relocation;
|
||||
bfd_vma gp, relocation;
|
||||
|
||||
/* FIXME: Does this case ever occur? */
|
||||
|
||||
ret = mips_elf_final_gp (output_bfd, symbol, true, error_message);
|
||||
ret = mips_elf_final_gp (output_bfd, symbol, true, error_message, &gp);
|
||||
if (ret != bfd_reloc_ok)
|
||||
return ret;
|
||||
|
||||
relocation = _bfd_get_gp_value (output_bfd) - reloc_entry->address;
|
||||
relocation = gp - reloc_entry->address;
|
||||
relocation += symbol->section->output_section->vma;
|
||||
relocation += symbol->section->output_offset;
|
||||
relocation += reloc_entry->addend;
|
||||
@ -953,29 +982,30 @@ mips_elf_got16_reloc (abfd,
|
||||
external symbol if we are producing relocateable output. */
|
||||
|
||||
static bfd_reloc_status_type
|
||||
mips_elf_final_gp (output_bfd, symbol, relocateable, error_message)
|
||||
mips_elf_final_gp (output_bfd, symbol, relocateable, error_message, pgp)
|
||||
bfd *output_bfd;
|
||||
asymbol *symbol;
|
||||
boolean relocateable;
|
||||
char **error_message;
|
||||
bfd_vma *pgp;
|
||||
{
|
||||
if (bfd_is_und_section (symbol->section)
|
||||
&& ! relocateable)
|
||||
return bfd_reloc_undefined;
|
||||
{
|
||||
*pgp = 0;
|
||||
return bfd_reloc_undefined;
|
||||
}
|
||||
|
||||
/* This doesn't work if the BFD is not ELF. */
|
||||
if (output_bfd->xvec->flavour != bfd_target_elf_flavour)
|
||||
abort ();
|
||||
|
||||
if (_bfd_get_gp_value (output_bfd) == 0
|
||||
*pgp = _bfd_get_gp_value (output_bfd);
|
||||
if (*pgp == 0
|
||||
&& (! relocateable
|
||||
|| (symbol->flags & BSF_SECTION_SYM) != 0))
|
||||
{
|
||||
if (relocateable)
|
||||
{
|
||||
/* Make up a value. */
|
||||
_bfd_set_gp_value (output_bfd,
|
||||
symbol->section->output_section->vma + 0x4000);
|
||||
*pgp = symbol->section->output_section->vma + 0x4000;
|
||||
_bfd_set_gp_value (output_bfd, *pgp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -997,7 +1027,8 @@ mips_elf_final_gp (output_bfd, symbol, relocateable, error_message)
|
||||
name = bfd_asymbol_name (*sym);
|
||||
if (*name == '_' && strcmp (name, "_gp") == 0)
|
||||
{
|
||||
_bfd_set_gp_value (output_bfd, bfd_asymbol_value (*sym));
|
||||
*pgp = bfd_asymbol_value (*sym);
|
||||
_bfd_set_gp_value (output_bfd, *pgp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1006,7 +1037,8 @@ mips_elf_final_gp (output_bfd, symbol, relocateable, error_message)
|
||||
if (i >= count)
|
||||
{
|
||||
/* Only get the error once. */
|
||||
_bfd_set_gp_value (output_bfd, 4);
|
||||
*pgp = 4;
|
||||
_bfd_set_gp_value (output_bfd, *pgp);
|
||||
*error_message =
|
||||
(char *) "GP relative relocation when _gp not defined";
|
||||
return bfd_reloc_dangerous;
|
||||
@ -1045,6 +1077,7 @@ mips_elf_gprel16_reloc (abfd,
|
||||
{
|
||||
boolean relocateable;
|
||||
bfd_reloc_status_type ret;
|
||||
bfd_vma gp;
|
||||
|
||||
/* If we're relocating, and this is an external symbol with no
|
||||
addend, we don't want to change anything. We will only have an
|
||||
@ -1066,13 +1099,13 @@ mips_elf_gprel16_reloc (abfd,
|
||||
output_bfd = symbol->section->output_section->owner;
|
||||
}
|
||||
|
||||
ret = mips_elf_final_gp (output_bfd, symbol, relocateable, error_message);
|
||||
ret = mips_elf_final_gp (output_bfd, symbol, relocateable, error_message,
|
||||
&gp);
|
||||
if (ret != bfd_reloc_ok)
|
||||
return ret;
|
||||
|
||||
return gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
|
||||
relocateable, data,
|
||||
_bfd_get_gp_value (output_bfd));
|
||||
relocateable, data, gp);
|
||||
}
|
||||
|
||||
static bfd_reloc_status_type
|
||||
@ -1153,6 +1186,7 @@ mips_elf_gprel32_reloc (abfd,
|
||||
{
|
||||
boolean relocateable;
|
||||
bfd_reloc_status_type ret;
|
||||
bfd_vma gp;
|
||||
|
||||
/* If we're relocating, and this is an external symbol with no
|
||||
addend, we don't want to change anything. We will only have an
|
||||
@ -1168,21 +1202,23 @@ mips_elf_gprel32_reloc (abfd,
|
||||
}
|
||||
|
||||
if (output_bfd != (bfd *) NULL)
|
||||
relocateable = true;
|
||||
{
|
||||
relocateable = true;
|
||||
gp = _bfd_get_gp_value (output_bfd);
|
||||
}
|
||||
else
|
||||
{
|
||||
relocateable = false;
|
||||
output_bfd = symbol->section->output_section->owner;
|
||||
|
||||
ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
|
||||
error_message);
|
||||
error_message, &gp);
|
||||
if (ret != bfd_reloc_ok)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
|
||||
relocateable, data,
|
||||
_bfd_get_gp_value (output_bfd));
|
||||
relocateable, data, gp);
|
||||
}
|
||||
|
||||
static bfd_reloc_status_type
|
||||
@ -2366,15 +2402,13 @@ mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
|
||||
struct fdr *fdr_ptr;
|
||||
|
||||
fi = ((struct mips_elf_find_line *)
|
||||
bfd_alloc (abfd, sizeof (struct mips_elf_find_line)));
|
||||
bfd_zalloc (abfd, sizeof (struct mips_elf_find_line)));
|
||||
if (fi == NULL)
|
||||
{
|
||||
msec->flags = origflags;
|
||||
return false;
|
||||
}
|
||||
|
||||
memset (fi, 0, sizeof (struct mips_elf_find_line));
|
||||
|
||||
if (! mips_elf_read_ecoff_info (abfd, msec, &fi->d))
|
||||
{
|
||||
msec->flags = origflags;
|
||||
@ -2436,6 +2470,9 @@ struct mips_elf_link_hash_entry
|
||||
|
||||
/* External symbol information. */
|
||||
EXTR esym;
|
||||
|
||||
/* Number of MIPS_32 or MIPS_REL32 relocs against this symbol. */
|
||||
unsigned int mips_32_relocs;
|
||||
};
|
||||
|
||||
/* MIPS ELF linker hash table. */
|
||||
@ -2505,6 +2542,7 @@ mips_elf_link_hash_newfunc (entry, table, string)
|
||||
/* We use -2 as a marker to indicate that the information has
|
||||
not been set. -1 means there is no associated ifd. */
|
||||
ret->esym.ifd = -2;
|
||||
ret->mips_32_relocs = 0;
|
||||
}
|
||||
|
||||
return (struct bfd_hash_entry *) ret;
|
||||
@ -2853,6 +2891,7 @@ mips_elf_create_procedure_table (handle, abfd, info, s, debug)
|
||||
rpdr = NULL;
|
||||
esym = NULL;
|
||||
ss = NULL;
|
||||
sv = NULL;
|
||||
|
||||
swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
|
||||
|
||||
@ -2895,9 +2934,9 @@ mips_elf_create_procedure_table (handle, abfd, info, s, debug)
|
||||
goto error_return;
|
||||
|
||||
count = hdr->ipdMax;
|
||||
for (i = 0; i < count; i++, rp++, epdr++)
|
||||
for (i = 0; i < count; i++, rp++)
|
||||
{
|
||||
(*swap->swap_pdr_in) (abfd, (PTR) epdr, &pdr);
|
||||
(*swap->swap_pdr_in) (abfd, (PTR) (epdr + i), &pdr);
|
||||
(*swap->swap_sym_in) (abfd, (PTR) &esym[pdr.isym], &sym);
|
||||
rp->adr = sym.value;
|
||||
rp->regmask = pdr.regmask;
|
||||
@ -2925,7 +2964,7 @@ mips_elf_create_procedure_table (handle, abfd, info, s, debug)
|
||||
mips_elf_hash_table (info)->procedure_count = count + 2;
|
||||
|
||||
erp = (struct rpdr_ext *) rtproc;
|
||||
memset (rp, 0, sizeof (struct rpdr_ext));
|
||||
memset (erp, 0, sizeof (struct rpdr_ext));
|
||||
erp++;
|
||||
str = (char *) rtproc + sizeof (struct rpdr_ext) * (count + 2);
|
||||
strcpy (str, no_name_func);
|
||||
@ -2946,11 +2985,16 @@ mips_elf_create_procedure_table (handle, abfd, info, s, debug)
|
||||
matters, but someday it might). */
|
||||
s->link_order_head = (struct bfd_link_order *) NULL;
|
||||
|
||||
free (epdr);
|
||||
free (rpdr);
|
||||
free (esym);
|
||||
free (ss);
|
||||
free (sv);
|
||||
if (epdr != NULL)
|
||||
free (epdr);
|
||||
if (rpdr != NULL)
|
||||
free (rpdr);
|
||||
if (esym != NULL)
|
||||
free (esym);
|
||||
if (ss != NULL)
|
||||
free (ss);
|
||||
if (sv != NULL)
|
||||
free (sv);
|
||||
|
||||
return true;
|
||||
|
||||
@ -3769,6 +3813,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
size_t extsymoff;
|
||||
asection *sgot, *sreloc, *scpt;
|
||||
bfd *dynobj;
|
||||
bfd_vma gp;
|
||||
Elf_Internal_Rela *rel;
|
||||
Elf_Internal_Rela *relend;
|
||||
struct mips_got_info *g;
|
||||
@ -3795,6 +3840,8 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
extsymoff = symtab_hdr->sh_info;
|
||||
}
|
||||
|
||||
gp = _bfd_get_gp_value (output_bfd);
|
||||
|
||||
rel = relocs;
|
||||
relend = relocs + input_section->reloc_count;
|
||||
for (; rel < relend; rel++)
|
||||
@ -3803,7 +3850,6 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
reloc_howto_type *howto;
|
||||
unsigned long r_symndx;
|
||||
bfd_vma addend;
|
||||
bfd_vma gp;
|
||||
struct elf_link_hash_entry *h;
|
||||
asection *sec;
|
||||
Elf_Internal_Sym *sym;
|
||||
@ -3838,8 +3884,6 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
|
||||
gp = _bfd_get_gp_value (output_bfd);
|
||||
|
||||
/* Mix in the change in GP address for a GP relative reloc. */
|
||||
if (r_type != R_MIPS_GPREL16
|
||||
&& r_type != R_MIPS_LITERAL
|
||||
@ -3921,17 +3965,40 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
/* If this is HI16 or GOT16 with an associated LO16,
|
||||
adjust the addend accordingly. Otherwise, just
|
||||
relocate. */
|
||||
if ((r_type != R_MIPS_HI16 && r_type != R_MIPS_GOT16)
|
||||
|| (rel + 1) >= relend
|
||||
|| ELF32_R_TYPE ((rel + 1)->r_info) != R_MIPS_LO16)
|
||||
if (r_type != R_MIPS_HI16 && r_type != R_MIPS_GOT16)
|
||||
r = _bfd_relocate_contents (howto, input_bfd,
|
||||
addend,
|
||||
contents + rel->r_offset);
|
||||
else
|
||||
{
|
||||
mips_elf_relocate_hi16 (input_bfd, rel, rel + 1,
|
||||
contents, addend);
|
||||
r = bfd_reloc_ok;
|
||||
Elf_Internal_Rela *lorel;
|
||||
|
||||
/* As a GNU extension, permit an arbitrary
|
||||
number of R_MIPS_HI16 relocs before the
|
||||
R_MIPS_LO16 reloc. This permits gcc to emit
|
||||
the HI and LO relocs itself. */
|
||||
if (r_type == R_MIPS_GOT16)
|
||||
lorel = rel + 1;
|
||||
else
|
||||
{
|
||||
for (lorel = rel + 1;
|
||||
(lorel < relend
|
||||
&& (ELF32_R_TYPE (lorel->r_info)
|
||||
== R_MIPS_HI16));
|
||||
lorel++)
|
||||
;
|
||||
}
|
||||
if (lorel < relend
|
||||
&& ELF32_R_TYPE (lorel->r_info) == R_MIPS_LO16)
|
||||
{
|
||||
mips_elf_relocate_hi16 (input_bfd, rel, lorel,
|
||||
contents, addend);
|
||||
r = bfd_reloc_ok;
|
||||
}
|
||||
else
|
||||
r = _bfd_relocate_contents (howto, input_bfd,
|
||||
addend,
|
||||
contents + rel->r_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4036,17 +4103,33 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
}
|
||||
}
|
||||
|
||||
if (r_type == R_MIPS_HI16
|
||||
&& (rel + 1) < relend
|
||||
&& ELF32_R_TYPE ((rel + 1)->r_info) == R_MIPS_LO16)
|
||||
if (r_type == R_MIPS_HI16)
|
||||
{
|
||||
mips_elf_relocate_hi16 (input_bfd, rel, rel + 1,
|
||||
contents, relocation + addend);
|
||||
r = bfd_reloc_ok;
|
||||
Elf_Internal_Rela *lorel;
|
||||
|
||||
/* As a GNU extension, permit an arbitrary number of
|
||||
R_MIPS_HI16 relocs before the R_MIPS_LO16 reloc.
|
||||
This permits gcc to emit the HI and LO relocs itself. */
|
||||
for (lorel = rel + 1;
|
||||
(lorel < relend
|
||||
&& ELF32_R_TYPE (lorel->r_info) == R_MIPS_HI16);
|
||||
lorel++)
|
||||
;
|
||||
if (lorel < relend
|
||||
&& ELF32_R_TYPE (lorel->r_info) == R_MIPS_LO16)
|
||||
{
|
||||
mips_elf_relocate_hi16 (input_bfd, rel, lorel,
|
||||
contents, relocation + addend);
|
||||
r = bfd_reloc_ok;
|
||||
}
|
||||
else
|
||||
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
|
||||
contents, rel->r_offset,
|
||||
relocation, addend);
|
||||
}
|
||||
else if (r_type == R_MIPS_GOT16 && local)
|
||||
{
|
||||
/* GOT16 must be also with associated LO16 in the local
|
||||
/* GOT16 must also have an associated LO16 in the local
|
||||
case. In this case, the addend is extracted and the
|
||||
section in which the referenced object is determined.
|
||||
Then the final address of the object is computed and
|
||||
@ -4120,7 +4203,10 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
Elf32_crinfo cptrel;
|
||||
bfd_byte *cr;
|
||||
|
||||
if (info->shared
|
||||
if ((info->shared
|
||||
|| (h != NULL
|
||||
&& ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
|
||||
== 0)))
|
||||
&& (input_section->flags & SEC_ALLOC) != 0)
|
||||
{
|
||||
/* When generating a shared object, these
|
||||
@ -4655,7 +4741,7 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
|
||||
|
||||
case R_MIPS_32:
|
||||
case R_MIPS_REL32:
|
||||
if (info->shared
|
||||
if ((info->shared || h != NULL)
|
||||
&& (sec->flags & SEC_ALLOC) != 0)
|
||||
{
|
||||
/* When creating a shared object, we must copy these
|
||||
@ -4686,7 +4772,17 @@ mips_elf_check_relocs (abfd, info, sec, relocs)
|
||||
}
|
||||
}
|
||||
|
||||
sreloc->_raw_size += sizeof (Elf32_External_Rel);
|
||||
if (info->shared)
|
||||
sreloc->_raw_size += sizeof (Elf32_External_Rel);
|
||||
else
|
||||
{
|
||||
struct mips_elf_link_hash_entry *hmips;
|
||||
|
||||
/* We only need to copy this reloc if the symbol is
|
||||
defined in a dynamic object. */
|
||||
hmips = (struct mips_elf_link_hash_entry *) h;
|
||||
++hmips->mips_32_relocs;
|
||||
}
|
||||
}
|
||||
|
||||
if (SGI_COMPAT (abfd))
|
||||
@ -4724,6 +4820,7 @@ mips_elf_adjust_dynamic_symbol (info, h)
|
||||
struct elf_link_hash_entry *h;
|
||||
{
|
||||
bfd *dynobj;
|
||||
struct mips_elf_link_hash_entry *hmips;
|
||||
asection *s;
|
||||
|
||||
dynobj = elf_hash_table (info)->dynobj;
|
||||
@ -4739,6 +4836,20 @@ mips_elf_adjust_dynamic_symbol (info, h)
|
||||
&& (h->elf_link_hash_flags
|
||||
& ELF_LINK_HASH_DEF_REGULAR) == 0)));
|
||||
|
||||
/* If this symbol is defined in a dynamic object, we need to copy
|
||||
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
|
||||
&& hmips->mips_32_relocs != 0
|
||||
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
|
||||
{
|
||||
s = bfd_get_section_by_name (dynobj, ".rel.dyn");
|
||||
BFD_ASSERT (s != NULL);
|
||||
|
||||
s->_raw_size += hmips->mips_32_relocs * sizeof (Elf32_External_Rel);
|
||||
}
|
||||
|
||||
/* For a function, create a stub, if needed. */
|
||||
if (h->type == STT_FUNC
|
||||
|| (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
|
||||
@ -5238,7 +5349,7 @@ mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
{
|
||||
sym->st_shndx = SHN_ABS;
|
||||
sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
|
||||
sym->st_value = _bfd_get_gp_value (output_bfd);
|
||||
sym->st_value = elf_gp (output_bfd);
|
||||
}
|
||||
else if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0
|
||||
|| strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0)
|
||||
|
Loading…
Reference in New Issue
Block a user