diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f43cfe8c67..8e7fc5a173 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 3ad2f0a1b6..d013bc192a 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 2555c0cbd9..bd2c742cdb 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 0d20c4ba74..d4d503d2c3 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. */