Apply several patches from Maciej W. Rozycki

This commit is contained in:
Nick Clifton 2001-02-11 23:11:41 +00:00
parent ecd0338944
commit 9117d2197e
6 changed files with 152 additions and 46 deletions

View File

@ -1,3 +1,36 @@
2001-02-11 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
* elf32-mips.c (mips_elf_create_dynamic_relocation): Undo patch
from 2000-10-13. Do not add the symbol's value for R_MIPS_REL32
relocations against dynsym symbols.
* elf32-mips.c (elf_mips_howto_table): Fix the comment on
the R_MIPS_26 relocation.
(mips_elf_calculate_relocation): Use (p + 4) instead of p for
the R_MIPS_26 relocation.
(mips_elf_perform_relocation): Fix the comment on the R_MIPS16_26
relocation.
* elf64-mips.c (mips_elf64_howto_table_rel): Fix the comment on
the R_MIPS_26 relocation.
(mips_elf64_howto_table_rela): Likewise.
* elf32-mips.c (struct mips_elf_link_hash_entry): Added no_fn_stub
member to mark symbols that have non-CALL relocations against
them.
(mips_elf_link_hash_newfunc): Initialize no_fn_stub.
(mips_elf_calculate_relocation): Handle R_MIPS_CALL16 like
R_MIPS_GOT16.
(_bfd_mips_elf_check_relocs): Set no_fn_stub for a symbol if a
non-CALL relocation against it is encountered.
(_bfd_mips_elf_copy_indirect_symbol): Merge no_fn_stub as well.
(_bfd_mips_elf_adjust_dynamic_symbol): Only create a stub if
no_fn_stub is not set.
* elf32-mips.c (mips_elf_output_extsym): Get the output section
information from the real symbol for indirect ones.
Check no_fn_stub to find out if a symbol has a function stub
indeed.
2001-02-11 Michael Sokolov <msokolov@ivan.Harhan.ORG>
* Makefile.am (stamp-lib): ranlib the libbfd.a in the build directory.

View File

@ -80,6 +80,12 @@ struct mips_elf_link_hash_entry
section) against this symbol. */
unsigned int min_dyn_reloc_index;
/* We must not create a stub for a symbol that has relocations
related to taking the function's address, i.e. any but
R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition",
p. 4-20. */
boolean no_fn_stub;
/* If there is a stub that 32 bit functions should use to call this
16 bit function, this points to the section containing the stub. */
asection *fn_stub;
@ -193,7 +199,7 @@ static bfd_vma mips_elf_got16_entry
static boolean mips_elf_create_dynamic_relocation
PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *,
struct mips_elf_link_hash_entry *, asection *,
bfd_vma, bfd_vma *, asection *, boolean local_p));
bfd_vma, bfd_vma *, asection *));
static void mips_elf_allocate_dynamic_relocations
PARAMS ((bfd *, unsigned int));
static boolean mips_elf_stub_section_p
@ -531,7 +537,7 @@ static reloc_howto_type elf_mips_howto_table[] =
complain_overflow_dont, /* complain_on_overflow */
/* This needs complex overflow
detection, because the upper four
bits must match the PC. */
bits must match the PC + 4. */
bfd_elf_generic_reloc, /* special_function */
"R_MIPS_26", /* name */
true, /* partial_inplace */
@ -3955,6 +3961,7 @@ mips_elf_link_hash_newfunc (entry, table, string)
ret->esym.ifd = -2;
ret->possibly_dynamic_relocs = 0;
ret->min_dyn_reloc_index = 0;
ret->no_fn_stub = false;
ret->fn_stub = NULL;
ret->need_fn_stub = false;
ret->call_stub = NULL;
@ -4330,24 +4337,36 @@ mips_elf_output_extsym (h, data)
}
else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
{
/* Set type and value for a symbol with a function stub. */
h->esym.asym.st = stProc;
sec = h->root.root.u.def.section;
if (sec == NULL)
h->esym.asym.value = 0;
else
struct mips_elf_link_hash_entry *hd = h;
boolean no_fn_stub = h->no_fn_stub;
while (hd->root.root.type == bfd_link_hash_indirect)
{
output_section = sec->output_section;
if (output_section != NULL)
h->esym.asym.value = (h->root.plt.offset
+ sec->output_offset
+ output_section->vma);
else
h->esym.asym.value = 0;
hd = (struct mips_elf_link_hash_entry *)h->root.root.u.i.link;
no_fn_stub = no_fn_stub || hd->no_fn_stub;
}
if (!no_fn_stub)
{
/* Set type and value for a symbol with a function stub. */
h->esym.asym.st = stProc;
sec = hd->root.root.u.def.section;
if (sec == NULL)
h->esym.asym.value = 0;
else
{
output_section = sec->output_section;
if (output_section != NULL)
h->esym.asym.value = (hd->root.plt.offset
+ sec->output_offset
+ output_section->vma);
else
h->esym.asym.value = 0;
}
#if 0 /* FIXME? */
h->esym.ifd = 0;
h->esym.ifd = 0;
#endif
}
}
if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
@ -5748,7 +5767,7 @@ mips_elf_next_relocation (r_type, relocation, relend)
static boolean
mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
symbol, addendp, input_section, local_p)
symbol, addendp, input_section)
bfd *output_bfd;
struct bfd_link_info *info;
const Elf_Internal_Rela *rel;
@ -5757,7 +5776,6 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
bfd_vma symbol;
bfd_vma *addendp;
asection *input_section;
boolean local_p;
{
Elf_Internal_Rel outrel;
boolean skip;
@ -5842,15 +5860,16 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
/* The relocation we're building is section-relative.
Therefore, the original addend must be adjusted by the
section offset. */
*addendp += symbol - sec->output_section->vma;
*addendp += section_offset;
/* Now, the relocation is just against the section. */
symbol = sec->output_section->vma;
}
/* If the relocation is against a local symbol was previously an
absolute relocation, we must adjust it by the value we give
it in the dynamic symbol table. */
if (local_p && r_type != R_MIPS_REL32)
/* If the relocation was previously an absolute relocation and
this symbol will not be referred to by the relocation, we must
adjust it by the value we give it in the dynamic symbol table.
Otherwise leave the job up to the dynamic linker. */
if (!indx && r_type != R_MIPS_REL32)
*addendp += symbol;
/* The relocation is always an REL32 relocation because we don't
@ -6225,7 +6244,7 @@ mips_elf_calculate_relocation (abfd,
symbol + addend, sgot->contents + g);
}
}
else if (r_type == R_MIPS_GOT16)
else if (r_type == R_MIPS_GOT16 || r_type == R_MIPS_CALL16)
/* There's no need to create a local GOT entry here; the
calculation for a local GOT16 entry does not involve G. */
break;
@ -6288,7 +6307,7 @@ mips_elf_calculate_relocation (abfd,
sec,
symbol,
&value,
input_section, local_p))
input_section))
return false;
}
else
@ -6320,14 +6339,14 @@ mips_elf_calculate_relocation (abfd,
break;
case R_MIPS16_26:
/* The calculation for R_MIPS_26 is just the same as for an
/* The calculation for R_MIPS16_26 is just the same as for an
R_MIPS_26. It's only the storage of the relocated field into
the output file that's different. That's handled in
mips_elf_perform_relocation. So, we just fall through to the
R_MIPS_26 case here. */
case R_MIPS_26:
if (local_p)
value = (((addend << 2) | (p & 0xf0000000)) + symbol) >> 2;
value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
else
value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
value &= howto->dst_mask;
@ -6393,6 +6412,7 @@ mips_elf_calculate_relocation (abfd,
break;
case R_MIPS_GOT16:
case R_MIPS_CALL16:
if (local_p)
{
boolean forced;
@ -6415,7 +6435,6 @@ mips_elf_calculate_relocation (abfd,
/* Fall through. */
case R_MIPS_CALL16:
case R_MIPS_GOT_DISP:
value = g;
overflowed_p = mips_elf_overflow_p (value, 16);
@ -6620,9 +6639,9 @@ mips_elf_perform_relocation (info, howto, relocation, value,
((sub1 << 16) | sub2)).
When producing a relocateable object file, the calculation is
(((A < 2) | (P & 0xf0000000) + S) >> 2)
(((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
When producing a fully linked file, the calculation is
let R = (((A < 2) | (P & 0xf0000000) + S) >> 2)
let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff) */
if (!info->relocateable)
@ -7728,10 +7747,10 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
/* We may need a local GOT entry for this relocation. We
don't count R_MIPS_GOT_PAGE because we can estimate the
maximum number of pages needed by looking at the size of
the segment. Similar comments apply to R_MIPS_GOT16. 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.
the segment. Similar comments apply to R_MIPS_GOT16 and
R_MIPS_CALL16. 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.
This estimation is very conservative since we can merge
duplicate entries in the GOT. In order to be less
@ -7863,6 +7882,25 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
break;
}
/* We must not create a stub for a symbol that has relocations
related to taking the function's address. */
switch (r_type)
{
default:
if (h != NULL)
{
struct mips_elf_link_hash_entry *mh;
mh = (struct mips_elf_link_hash_entry *) h;
mh->no_fn_stub = true;
}
break;
case R_MIPS_CALL16:
case R_MIPS_CALL_HI16:
case R_MIPS_CALL_LO16:
break;
}
/* If this reloc is not a 16 bit call, and it has a global
symbol, then we will need the fn_stub if there is one.
References from a stub section do not count. */
@ -7998,6 +8036,8 @@ _bfd_mips_elf_copy_indirect_symbol (dir, ind)
|| (indmips->min_dyn_reloc_index != 0
&& indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index))
dirmips->min_dyn_reloc_index = indmips->min_dyn_reloc_index;
if (indmips->no_fn_stub)
dirmips->no_fn_stub = true;
}
/* Adjust a symbol defined by a dynamic object and referenced by a
@ -8038,8 +8078,9 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h)
mips_elf_allocate_dynamic_relocations (dynobj,
hmips->possibly_dynamic_relocs);
/* For a function, create a stub, if needed. */
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
/* For a function, create a stub, if allowed. */
if (! hmips->no_fn_stub
&& (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
{
if (! elf_hash_table (info)->dynamic_sections_created)
return true;

View File

@ -1,3 +1,12 @@
2001-02-11 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
* config/tc-mips.c (macro): For M_LA_AB emit a
BFD_RELOC_MIPS_CALL16 relocation or a
BFD_RELOC_MIPS_CALL_HI16/BFD_RELOC_MIPS_CALL_LO16 pair instead of
BFD_RELOC_MIPS_GOT16 and
BFD_RELOC_MIPS_GOT_HI16/BFD_RELOC_MIPS_GOT_LO16, respectively for
loading the jump register when generating SVR4_PIC code.
2001-02-10 Chris Demetriou <cgd@broadcom.com>
* configure.in: Make 'mipself' and 'mipsecoff' emulations

View File

@ -3936,7 +3936,7 @@ macro (ip)
if (mips_trap)
macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0);
else
macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
return;
}
@ -3957,7 +3957,7 @@ macro (ip)
macro_build ((char *) NULL, &icnt, NULL,
dbl ? "ddiv" : "div",
"z,s,t", sreg, treg);
macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);
}
expr1.X_add_number = -1;
macro_build ((char *) NULL, &icnt, &expr1,
@ -3996,7 +3996,7 @@ macro (ip)
that later insns are available for delay slot filling. */
--mips_opts.noreorder;
macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);
}
macro_build ((char *) NULL, &icnt, NULL, s, "d", dreg);
break;
@ -4213,9 +4213,13 @@ macro (ip)
}
else if (mips_pic == SVR4_PIC && ! mips_big_got)
{
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
/* If this is a reference to an external symbol, and there
is no constant, we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
or if tempreg is PIC_CALL_REG
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_CALL16)
For a local symbol, we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
@ -4242,9 +4246,11 @@ macro (ip)
expr1.X_add_number = offset_expr.X_add_number;
offset_expr.X_add_number = 0;
frag_grow (32);
if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16;
macro_build ((char *) NULL, &icnt, &offset_expr,
dbl ? "ld" : "lw",
"t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);
"t,o(b)", tempreg, lw_reloc_type, GP);
if (expr1.X_add_number == 0)
{
int off;
@ -4350,12 +4356,18 @@ macro (ip)
else if (mips_pic == SVR4_PIC)
{
int gpdel;
int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16;
int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16;
/* This is the large GOT case. If this is a reference to an
external symbol, and there is no constant, we want
lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
addu $tempreg,$tempreg,$gp
lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
or if tempreg is PIC_CALL_REG
lui $tempreg,<sym> (BFD_RELOC_MIPS_CALL_HI16)
addu $tempreg,$tempreg,$gp
lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_CALL_LO16)
For a local symbol, we want
lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT16)
nop
@ -4394,8 +4406,13 @@ macro (ip)
gpdel = 4;
else
gpdel = 0;
if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG)
{
lui_reloc_type = (int) BFD_RELOC_MIPS_CALL_HI16;
lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16;
}
macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",
tempreg, (int) BFD_RELOC_MIPS_GOT_HI16);
tempreg, lui_reloc_type);
macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
((bfd_arch_bits_per_address (stdoutput) == 32
|| ! ISA_HAS_64BIT_REGS (mips_opts.isa))
@ -4403,8 +4420,7 @@ macro (ip)
"d,v,t", tempreg, tempreg, GP);
macro_build ((char *) NULL, &icnt, &offset_expr,
dbl ? "ld" : "lw",
"t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT_LO16,
tempreg);
"t,o(b)", tempreg, lw_reloc_type, tempreg);
if (expr1.X_add_number == 0)
{
int off;

View File

@ -1,3 +1,10 @@
2001-02-11 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
* mips-dis.c (print_insn_arg): Use top four bits of the address of
the following instruction not of the jump itself for the jump
target.
(print_mips16_insn_arg): Likewise.
2001-02-11 Michael Sokolov <msokolov@ivan.Harhan.ORG>
* Makefile.am (stamp-lib): ranlib the libopcodes.a in the build

View File

@ -137,7 +137,7 @@ print_insn_arg (d, l, pc, info)
case 'a':
(*info->print_address_func)
(((pc & ~ (bfd_vma) 0x0fffffff)
((((pc + 4) & ~ (bfd_vma) 0x0fffffff)
| (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
info);
break;
@ -1038,9 +1038,9 @@ print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
if (! use_extend)
extend = 0;
l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
(*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
(*info->print_address_func) (((memaddr + 4) & 0xf0000000) | l, info);
info->insn_type = dis_jsr;
info->target = (memaddr & 0xf0000000) | l;
info->target = ((memaddr + 4) & 0xf0000000) | l;
info->branch_delay_insns = 1;
break;