aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1994-06-14 17:06:08 +0000
committerIan Lance Taylor <ian@airs.com>1994-06-14 17:06:08 +0000
commitac9ed09667f63fe7bad504e039e50a84cc860d9c (patch)
tree2b797cccc17fb3afededc1fdbf9c89086b7191ff
parente884f418024990e23d60c276025e52050304518b (diff)
downloadfsf-binutils-gdb-ac9ed09667f63fe7bad504e039e50a84cc860d9c.zip
fsf-binutils-gdb-ac9ed09667f63fe7bad504e039e50a84cc860d9c.tar.gz
fsf-binutils-gdb-ac9ed09667f63fe7bad504e039e50a84cc860d9c.tar.bz2
For PR 4865.
* libecoff.h (struct ecoff_link_hash_entry): Change type of written from boolean to char. Add new field small. * ecoff.c (ecoff_link_hash_newfunc): Initialize written to 0 rather than false. Initialize small to 0. (ecoff_link_add_externals): If ECOFF type is scSUndefined, set small. If small is set, and hash table type is common, force the symbol into a section named SCOMMON and change the ECOFF type from scCommon to scSCommon. (ecoff_link_write_external): Set written to 1 rather than true. * coff-mips.c (mips_relocate_section): Correct JMPADDR reloc overflow check to consider section VMA of input file.
-rw-r--r--bfd/ChangeLog14
-rw-r--r--bfd/coff-mips.c55
-rw-r--r--bfd/ecoff.c25
-rw-r--r--bfd/libecoff.h4
4 files changed, 96 insertions, 2 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index f43cfe8..8e7fc5a 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,17 @@
+Tue Jun 14 13:00:04 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * libecoff.h (struct ecoff_link_hash_entry): Change type of
+ written from boolean to char. Add new field small.
+ * ecoff.c (ecoff_link_hash_newfunc): Initialize written to 0
+ rather than false. Initialize small to 0.
+ (ecoff_link_add_externals): If ECOFF type is scSUndefined, set
+ small. If small is set, and hash table type is common, force the
+ symbol into a section named SCOMMON and change the ECOFF type from
+ scCommon to scSCommon.
+ (ecoff_link_write_external): Set written to 1 rather than true.
+ * coff-mips.c (mips_relocate_section): Correct JMPADDR reloc
+ overflow check to consider section VMA of input file.
+
Mon Jun 13 14:20:07 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
* aoutf1.h (aout_32_sunos4_write_object_contents): Handle a
diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c
index 3ad2f0a..d013bc1 100644
--- a/bfd/coff-mips.c
+++ b/bfd/coff-mips.c
@@ -1444,6 +1444,43 @@ mips_relocate_section (output_bfd, info, input_bfd, input_section,
}
}
+ /* If we are relaxing, and this is a reloc against the .text
+ segment, we may need to adjust it if some branches have been
+ expanded. The reloc types which are likely to occur in the
+ .text section are handled efficiently by mips_relax_section,
+ and thus do not need to be handled here. */
+ if (ecoff_data (input_bfd)->debug_info.adjust != NULL
+ && ! int_rel.r_extern
+ && int_rel.r_symndx == RELOC_SECTION_TEXT
+ && (strcmp (bfd_get_section_name (input_bfd, input_section),
+ ".text") != 0
+ || (int_rel.r_type != MIPS_R_PCREL16
+ && int_rel.r_type != MIPS_R_SWITCH
+ && int_rel.r_type != MIPS_R_RELHI
+ && int_rel.r_type != MIPS_R_RELLO)))
+ {
+ bfd_vma adr;
+ struct ecoff_value_adjust *a;
+
+ /* We need to get the addend so that we know whether we need
+ to adjust the address. */
+ BFD_ASSERT (int_rel.r_type == MIPS_R_REFWORD);
+
+ adr = bfd_get_32 (input_bfd,
+ (contents
+ + adjust
+ + int_rel.r_vaddr
+ - input_section->vma));
+
+ for (a = ecoff_data (input_bfd)->debug_info.adjust;
+ a != (struct ecoff_value_adjust *) NULL;
+ a = a->next)
+ {
+ if (adr >= a->start && adr < a->end)
+ addend += a->adjust;
+ }
+ }
+
if (info->relocateable)
{
/* We are generating relocateable output, and must convert
@@ -1587,6 +1624,7 @@ mips_relocate_section (output_bfd, info, input_bfd, input_section,
}
relocation += addend;
+ addend = 0;
/* Adjust a PC relative relocation by removing the reference
to the original address in the section and including the
@@ -1697,6 +1735,23 @@ mips_relocate_section (output_bfd, info, input_bfd, input_section,
}
}
+ /* MIPS_R_JMPADDR requires peculiar overflow detection. The
+ instruction provides a 28 bit address (the two lower bits are
+ implicit zeroes) which is combined with the upper four bits
+ of the instruction address. */
+ if (r == bfd_reloc_ok
+ && int_rel.r_type == MIPS_R_JMPADDR
+ && (((relocation
+ + addend
+ + (int_rel.r_extern ? 0 : s->vma))
+ & 0xf0000000)
+ != ((input_section->output_section->vma
+ + input_section->output_offset
+ + (int_rel.r_vaddr - input_section->vma)
+ + adjust)
+ & 0xf0000000)))
+ r = bfd_reloc_overflow;
+
if (r != bfd_reloc_ok)
{
switch (r)
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 2555c0c..bd2c742 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -3575,6 +3575,8 @@ ecoff_link_hash_newfunc (entry, table, string)
/* Set local fields. */
ret->indx = -1;
ret->abfd = NULL;
+ ret->written = 0;
+ ret->small = 0;
}
memset ((PTR) &ret->esym, 0, sizeof ret->esym);
@@ -4171,6 +4173,25 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
h->abfd = abfd;
h->esym = esym;
}
+
+ /* Remember whether this symbol was small undefined. */
+ if (esym.asym.sc == scSUndefined)
+ h->small = 1;
+
+ /* If this symbol was ever small undefined, it needs to wind
+ up in a GP relative section. We can't control the
+ section of a defined symbol, but we can control the
+ section of a common symbol. This case is actually needed
+ on Ultrix 4.2 to handle the symbol cred in -lckrb. */
+ if (h->small
+ && h->root.type == bfd_link_hash_common
+ && strcmp (h->root.u.c.section->name, SCOMMON) != 0)
+ {
+ h->root.u.c.section = bfd_make_section_old_way (abfd, SCOMMON);
+ h->root.u.c.section->flags = SEC_ALLOC;
+ if (h->esym.asym.sc == scCommon)
+ h->esym.asym.sc = scSCommon;
+ }
}
}
@@ -4506,7 +4527,7 @@ ecoff_link_write_external (h, data)
/* FIXME: We should check if this symbol is being stripped. */
- if (h->root.written)
+ if (h->written)
return true;
if (h->abfd == (bfd *) NULL)
@@ -4607,7 +4628,7 @@ ecoff_link_write_external (h, data)
/* bfd_ecoff_debug_one_external uses iextMax to keep track of the
symbol number. */
h->indx = ecoff_data (output_bfd)->debug_info.symbolic_header.iextMax;
- h->root.written = true;
+ h->written = 1;
return (bfd_ecoff_debug_one_external
(output_bfd, &ecoff_data (output_bfd)->debug_info,
diff --git a/bfd/libecoff.h b/bfd/libecoff.h
index 0d20c4b..d4d503d 100644
--- a/bfd/libecoff.h
+++ b/bfd/libecoff.h
@@ -206,6 +206,10 @@ struct ecoff_link_hash_entry
bfd *abfd;
/* ECOFF external symbol information. */
EXTR esym;
+ /* Nonzero if this symbol has been written out. */
+ char written;
+ /* Nonzero if this symbol was referred to as small undefined. */
+ char small;
};
/* ECOFF linker hash table. */