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>
|
Fri Apr 26 18:00:37 1996 Ian Lance Taylor <ian@cygnus.com>
|
||||||
|
|
||||||
* ecoff.c (ecoff_compute_section_file_positions): Track the real
|
* 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 *,
|
PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
|
||||||
const char **, flagword *, asection **, bfd_vma *));
|
const char **, flagword *, asection **, bfd_vma *));
|
||||||
static bfd_reloc_status_type mips_elf_final_gp
|
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
|
static bfd_byte *elf32_mips_get_relocated_section_contents
|
||||||
PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
|
PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
|
||||||
bfd_byte *, boolean, asymbol **));
|
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
|
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
|
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
|
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;
|
struct mips_hi16
|
||||||
static bfd_vma mips_hi16_addend;
|
{
|
||||||
|
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
|
static bfd_reloc_status_type
|
||||||
mips_elf_hi16_reloc (abfd,
|
mips_elf_hi16_reloc (abfd,
|
||||||
@ -743,6 +754,7 @@ mips_elf_hi16_reloc (abfd,
|
|||||||
{
|
{
|
||||||
bfd_reloc_status_type ret;
|
bfd_reloc_status_type ret;
|
||||||
bfd_vma relocation;
|
bfd_vma relocation;
|
||||||
|
struct mips_hi16 *n;
|
||||||
|
|
||||||
/* If we're relocating, and this an external symbol, we don't want
|
/* If we're relocating, and this an external symbol, we don't want
|
||||||
to change anything. */
|
to change anything. */
|
||||||
@ -759,6 +771,7 @@ mips_elf_hi16_reloc (abfd,
|
|||||||
if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
|
if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
|
||||||
{
|
{
|
||||||
boolean relocateable;
|
boolean relocateable;
|
||||||
|
bfd_vma gp;
|
||||||
|
|
||||||
if (ret == bfd_reloc_undefined)
|
if (ret == bfd_reloc_undefined)
|
||||||
abort ();
|
abort ();
|
||||||
@ -772,11 +785,11 @@ mips_elf_hi16_reloc (abfd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
|
ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
|
||||||
error_message);
|
error_message, &gp);
|
||||||
if (ret != bfd_reloc_ok)
|
if (ret != bfd_reloc_ok)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
relocation = _bfd_get_gp_value (output_bfd) - reloc_entry->address;
|
relocation = gp - reloc_entry->address;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -798,8 +811,13 @@ mips_elf_hi16_reloc (abfd,
|
|||||||
return bfd_reloc_outofrange;
|
return bfd_reloc_outofrange;
|
||||||
|
|
||||||
/* Save the information, and let LO16 do the actual relocation. */
|
/* Save the information, and let LO16 do the actual relocation. */
|
||||||
mips_hi16_addr = (bfd_byte *) data + reloc_entry->address;
|
n = (struct mips_hi16 *) bfd_malloc (sizeof *n);
|
||||||
mips_hi16_addend = relocation;
|
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)
|
if (output_bfd != (bfd *) NULL)
|
||||||
reloc_entry->address += input_section->output_offset;
|
reloc_entry->address += input_section->output_offset;
|
||||||
@ -829,56 +847,67 @@ mips_elf_lo16_reloc (abfd,
|
|||||||
{
|
{
|
||||||
arelent gp_disp_relent;
|
arelent gp_disp_relent;
|
||||||
|
|
||||||
if (mips_hi16_addr != (bfd_byte *) NULL)
|
if (mips_hi16_list != NULL)
|
||||||
{
|
{
|
||||||
unsigned long insn;
|
struct mips_hi16 *l;
|
||||||
unsigned long val;
|
|
||||||
unsigned long vallo;
|
|
||||||
|
|
||||||
/* Do the HI16 relocation. Note that we actually don't need to
|
l = mips_hi16_list;
|
||||||
know anything about the LO16 itself, except where to find the
|
while (l != NULL)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
gp_disp_relent = *reloc_entry;
|
unsigned long insn;
|
||||||
reloc_entry = &gp_disp_relent;
|
unsigned long val;
|
||||||
reloc_entry->addend = mips_hi16_addend;
|
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)
|
else if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
|
||||||
{
|
{
|
||||||
bfd_reloc_status_type ret;
|
bfd_reloc_status_type ret;
|
||||||
bfd_vma relocation;
|
bfd_vma gp, relocation;
|
||||||
|
|
||||||
/* FIXME: Does this case ever occur? */
|
/* 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)
|
if (ret != bfd_reloc_ok)
|
||||||
return ret;
|
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_section->vma;
|
||||||
relocation += symbol->section->output_offset;
|
relocation += symbol->section->output_offset;
|
||||||
relocation += reloc_entry->addend;
|
relocation += reloc_entry->addend;
|
||||||
@ -953,29 +982,30 @@ mips_elf_got16_reloc (abfd,
|
|||||||
external symbol if we are producing relocateable output. */
|
external symbol if we are producing relocateable output. */
|
||||||
|
|
||||||
static bfd_reloc_status_type
|
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;
|
bfd *output_bfd;
|
||||||
asymbol *symbol;
|
asymbol *symbol;
|
||||||
boolean relocateable;
|
boolean relocateable;
|
||||||
char **error_message;
|
char **error_message;
|
||||||
|
bfd_vma *pgp;
|
||||||
{
|
{
|
||||||
if (bfd_is_und_section (symbol->section)
|
if (bfd_is_und_section (symbol->section)
|
||||||
&& ! relocateable)
|
&& ! relocateable)
|
||||||
return bfd_reloc_undefined;
|
{
|
||||||
|
*pgp = 0;
|
||||||
|
return bfd_reloc_undefined;
|
||||||
|
}
|
||||||
|
|
||||||
/* This doesn't work if the BFD is not ELF. */
|
*pgp = _bfd_get_gp_value (output_bfd);
|
||||||
if (output_bfd->xvec->flavour != bfd_target_elf_flavour)
|
if (*pgp == 0
|
||||||
abort ();
|
|
||||||
|
|
||||||
if (_bfd_get_gp_value (output_bfd) == 0
|
|
||||||
&& (! relocateable
|
&& (! relocateable
|
||||||
|| (symbol->flags & BSF_SECTION_SYM) != 0))
|
|| (symbol->flags & BSF_SECTION_SYM) != 0))
|
||||||
{
|
{
|
||||||
if (relocateable)
|
if (relocateable)
|
||||||
{
|
{
|
||||||
/* Make up a value. */
|
/* Make up a value. */
|
||||||
_bfd_set_gp_value (output_bfd,
|
*pgp = symbol->section->output_section->vma + 0x4000;
|
||||||
symbol->section->output_section->vma + 0x4000);
|
_bfd_set_gp_value (output_bfd, *pgp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -997,7 +1027,8 @@ mips_elf_final_gp (output_bfd, symbol, relocateable, error_message)
|
|||||||
name = bfd_asymbol_name (*sym);
|
name = bfd_asymbol_name (*sym);
|
||||||
if (*name == '_' && strcmp (name, "_gp") == 0)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1006,7 +1037,8 @@ mips_elf_final_gp (output_bfd, symbol, relocateable, error_message)
|
|||||||
if (i >= count)
|
if (i >= count)
|
||||||
{
|
{
|
||||||
/* Only get the error once. */
|
/* Only get the error once. */
|
||||||
_bfd_set_gp_value (output_bfd, 4);
|
*pgp = 4;
|
||||||
|
_bfd_set_gp_value (output_bfd, *pgp);
|
||||||
*error_message =
|
*error_message =
|
||||||
(char *) "GP relative relocation when _gp not defined";
|
(char *) "GP relative relocation when _gp not defined";
|
||||||
return bfd_reloc_dangerous;
|
return bfd_reloc_dangerous;
|
||||||
@ -1045,6 +1077,7 @@ mips_elf_gprel16_reloc (abfd,
|
|||||||
{
|
{
|
||||||
boolean relocateable;
|
boolean relocateable;
|
||||||
bfd_reloc_status_type ret;
|
bfd_reloc_status_type ret;
|
||||||
|
bfd_vma gp;
|
||||||
|
|
||||||
/* If we're relocating, and this is an external symbol with no
|
/* 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
|
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;
|
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)
|
if (ret != bfd_reloc_ok)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
|
return gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
|
||||||
relocateable, data,
|
relocateable, data, gp);
|
||||||
_bfd_get_gp_value (output_bfd));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bfd_reloc_status_type
|
static bfd_reloc_status_type
|
||||||
@ -1153,6 +1186,7 @@ mips_elf_gprel32_reloc (abfd,
|
|||||||
{
|
{
|
||||||
boolean relocateable;
|
boolean relocateable;
|
||||||
bfd_reloc_status_type ret;
|
bfd_reloc_status_type ret;
|
||||||
|
bfd_vma gp;
|
||||||
|
|
||||||
/* If we're relocating, and this is an external symbol with no
|
/* 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
|
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)
|
if (output_bfd != (bfd *) NULL)
|
||||||
relocateable = true;
|
{
|
||||||
|
relocateable = true;
|
||||||
|
gp = _bfd_get_gp_value (output_bfd);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
relocateable = false;
|
relocateable = false;
|
||||||
output_bfd = symbol->section->output_section->owner;
|
output_bfd = symbol->section->output_section->owner;
|
||||||
|
|
||||||
ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
|
ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
|
||||||
error_message);
|
error_message, &gp);
|
||||||
if (ret != bfd_reloc_ok)
|
if (ret != bfd_reloc_ok)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
|
return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
|
||||||
relocateable, data,
|
relocateable, data, gp);
|
||||||
_bfd_get_gp_value (output_bfd));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bfd_reloc_status_type
|
static bfd_reloc_status_type
|
||||||
@ -2366,15 +2402,13 @@ mips_elf_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
|
|||||||
struct fdr *fdr_ptr;
|
struct fdr *fdr_ptr;
|
||||||
|
|
||||||
fi = ((struct mips_elf_find_line *)
|
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)
|
if (fi == NULL)
|
||||||
{
|
{
|
||||||
msec->flags = origflags;
|
msec->flags = origflags;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset (fi, 0, sizeof (struct mips_elf_find_line));
|
|
||||||
|
|
||||||
if (! mips_elf_read_ecoff_info (abfd, msec, &fi->d))
|
if (! mips_elf_read_ecoff_info (abfd, msec, &fi->d))
|
||||||
{
|
{
|
||||||
msec->flags = origflags;
|
msec->flags = origflags;
|
||||||
@ -2436,6 +2470,9 @@ struct mips_elf_link_hash_entry
|
|||||||
|
|
||||||
/* External symbol information. */
|
/* External symbol information. */
|
||||||
EXTR esym;
|
EXTR esym;
|
||||||
|
|
||||||
|
/* Number of MIPS_32 or MIPS_REL32 relocs against this symbol. */
|
||||||
|
unsigned int mips_32_relocs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* MIPS ELF linker hash table. */
|
/* 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
|
/* We use -2 as a marker to indicate that the information has
|
||||||
not been set. -1 means there is no associated ifd. */
|
not been set. -1 means there is no associated ifd. */
|
||||||
ret->esym.ifd = -2;
|
ret->esym.ifd = -2;
|
||||||
|
ret->mips_32_relocs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (struct bfd_hash_entry *) ret;
|
return (struct bfd_hash_entry *) ret;
|
||||||
@ -2853,6 +2891,7 @@ mips_elf_create_procedure_table (handle, abfd, info, s, debug)
|
|||||||
rpdr = NULL;
|
rpdr = NULL;
|
||||||
esym = NULL;
|
esym = NULL;
|
||||||
ss = NULL;
|
ss = NULL;
|
||||||
|
sv = NULL;
|
||||||
|
|
||||||
swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
|
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;
|
goto error_return;
|
||||||
|
|
||||||
count = hdr->ipdMax;
|
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);
|
(*swap->swap_sym_in) (abfd, (PTR) &esym[pdr.isym], &sym);
|
||||||
rp->adr = sym.value;
|
rp->adr = sym.value;
|
||||||
rp->regmask = pdr.regmask;
|
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;
|
mips_elf_hash_table (info)->procedure_count = count + 2;
|
||||||
|
|
||||||
erp = (struct rpdr_ext *) rtproc;
|
erp = (struct rpdr_ext *) rtproc;
|
||||||
memset (rp, 0, sizeof (struct rpdr_ext));
|
memset (erp, 0, sizeof (struct rpdr_ext));
|
||||||
erp++;
|
erp++;
|
||||||
str = (char *) rtproc + sizeof (struct rpdr_ext) * (count + 2);
|
str = (char *) rtproc + sizeof (struct rpdr_ext) * (count + 2);
|
||||||
strcpy (str, no_name_func);
|
strcpy (str, no_name_func);
|
||||||
@ -2946,11 +2985,16 @@ mips_elf_create_procedure_table (handle, abfd, info, s, debug)
|
|||||||
matters, but someday it might). */
|
matters, but someday it might). */
|
||||||
s->link_order_head = (struct bfd_link_order *) NULL;
|
s->link_order_head = (struct bfd_link_order *) NULL;
|
||||||
|
|
||||||
free (epdr);
|
if (epdr != NULL)
|
||||||
free (rpdr);
|
free (epdr);
|
||||||
free (esym);
|
if (rpdr != NULL)
|
||||||
free (ss);
|
free (rpdr);
|
||||||
free (sv);
|
if (esym != NULL)
|
||||||
|
free (esym);
|
||||||
|
if (ss != NULL)
|
||||||
|
free (ss);
|
||||||
|
if (sv != NULL)
|
||||||
|
free (sv);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -3769,6 +3813,7 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
size_t extsymoff;
|
size_t extsymoff;
|
||||||
asection *sgot, *sreloc, *scpt;
|
asection *sgot, *sreloc, *scpt;
|
||||||
bfd *dynobj;
|
bfd *dynobj;
|
||||||
|
bfd_vma gp;
|
||||||
Elf_Internal_Rela *rel;
|
Elf_Internal_Rela *rel;
|
||||||
Elf_Internal_Rela *relend;
|
Elf_Internal_Rela *relend;
|
||||||
struct mips_got_info *g;
|
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;
|
extsymoff = symtab_hdr->sh_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gp = _bfd_get_gp_value (output_bfd);
|
||||||
|
|
||||||
rel = relocs;
|
rel = relocs;
|
||||||
relend = relocs + input_section->reloc_count;
|
relend = relocs + input_section->reloc_count;
|
||||||
for (; rel < relend; rel++)
|
for (; rel < relend; rel++)
|
||||||
@ -3803,7 +3850,6 @@ mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
reloc_howto_type *howto;
|
reloc_howto_type *howto;
|
||||||
unsigned long r_symndx;
|
unsigned long r_symndx;
|
||||||
bfd_vma addend;
|
bfd_vma addend;
|
||||||
bfd_vma gp;
|
|
||||||
struct elf_link_hash_entry *h;
|
struct elf_link_hash_entry *h;
|
||||||
asection *sec;
|
asection *sec;
|
||||||
Elf_Internal_Sym *sym;
|
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);
|
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. */
|
/* Mix in the change in GP address for a GP relative reloc. */
|
||||||
if (r_type != R_MIPS_GPREL16
|
if (r_type != R_MIPS_GPREL16
|
||||||
&& r_type != R_MIPS_LITERAL
|
&& 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,
|
/* If this is HI16 or GOT16 with an associated LO16,
|
||||||
adjust the addend accordingly. Otherwise, just
|
adjust the addend accordingly. Otherwise, just
|
||||||
relocate. */
|
relocate. */
|
||||||
if ((r_type != R_MIPS_HI16 && r_type != R_MIPS_GOT16)
|
if (r_type != R_MIPS_HI16 && r_type != R_MIPS_GOT16)
|
||||||
|| (rel + 1) >= relend
|
|
||||||
|| ELF32_R_TYPE ((rel + 1)->r_info) != R_MIPS_LO16)
|
|
||||||
r = _bfd_relocate_contents (howto, input_bfd,
|
r = _bfd_relocate_contents (howto, input_bfd,
|
||||||
addend,
|
addend,
|
||||||
contents + rel->r_offset);
|
contents + rel->r_offset);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mips_elf_relocate_hi16 (input_bfd, rel, rel + 1,
|
Elf_Internal_Rela *lorel;
|
||||||
contents, addend);
|
|
||||||
r = bfd_reloc_ok;
|
/* 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
|
if (r_type == R_MIPS_HI16)
|
||||||
&& (rel + 1) < relend
|
|
||||||
&& ELF32_R_TYPE ((rel + 1)->r_info) == R_MIPS_LO16)
|
|
||||||
{
|
{
|
||||||
mips_elf_relocate_hi16 (input_bfd, rel, rel + 1,
|
Elf_Internal_Rela *lorel;
|
||||||
contents, relocation + addend);
|
|
||||||
r = bfd_reloc_ok;
|
/* 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)
|
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
|
case. In this case, the addend is extracted and the
|
||||||
section in which the referenced object is determined.
|
section in which the referenced object is determined.
|
||||||
Then the final address of the object is computed and
|
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;
|
Elf32_crinfo cptrel;
|
||||||
bfd_byte *cr;
|
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)
|
&& (input_section->flags & SEC_ALLOC) != 0)
|
||||||
{
|
{
|
||||||
/* When generating a shared object, these
|
/* 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_32:
|
||||||
case R_MIPS_REL32:
|
case R_MIPS_REL32:
|
||||||
if (info->shared
|
if ((info->shared || h != NULL)
|
||||||
&& (sec->flags & SEC_ALLOC) != 0)
|
&& (sec->flags & SEC_ALLOC) != 0)
|
||||||
{
|
{
|
||||||
/* When creating a shared object, we must copy these
|
/* 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))
|
if (SGI_COMPAT (abfd))
|
||||||
@ -4724,6 +4820,7 @@ mips_elf_adjust_dynamic_symbol (info, h)
|
|||||||
struct elf_link_hash_entry *h;
|
struct elf_link_hash_entry *h;
|
||||||
{
|
{
|
||||||
bfd *dynobj;
|
bfd *dynobj;
|
||||||
|
struct mips_elf_link_hash_entry *hmips;
|
||||||
asection *s;
|
asection *s;
|
||||||
|
|
||||||
dynobj = elf_hash_table (info)->dynobj;
|
dynobj = elf_hash_table (info)->dynobj;
|
||||||
@ -4739,6 +4836,20 @@ mips_elf_adjust_dynamic_symbol (info, h)
|
|||||||
&& (h->elf_link_hash_flags
|
&& (h->elf_link_hash_flags
|
||||||
& ELF_LINK_HASH_DEF_REGULAR) == 0)));
|
& 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. */
|
/* For a function, create a stub, if needed. */
|
||||||
if (h->type == STT_FUNC
|
if (h->type == STT_FUNC
|
||||||
|| (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
|
|| (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_shndx = SHN_ABS;
|
||||||
sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
|
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
|
else if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0
|
||||||
|| strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0)
|
|| strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user