aboutsummaryrefslogtreecommitdiff
path: root/bfd/ecofflink.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1994-03-25 22:37:55 +0000
committerIan Lance Taylor <ian@airs.com>1994-03-25 22:37:55 +0000
commita3a33af390c3a99e00b20847a102e307cfb538c7 (patch)
treeb262eb6f85a5b10fe60cdc47a0f753178e889283 /bfd/ecofflink.c
parentf078dc7cf26a816ef0bb66be8b819ac549486e86 (diff)
downloadgdb-a3a33af390c3a99e00b20847a102e307cfb538c7.zip
gdb-a3a33af390c3a99e00b20847a102e307cfb538c7.tar.gz
gdb-a3a33af390c3a99e00b20847a102e307cfb538c7.tar.bz2
Changes to support linker relaxing of embedded MIPS PIC code to
use a five instruction sequence for funtion calls which are out of range of the bal instruction. * libecoff.h (struct ecoff_section_tdata): Define. (ecoff_section_data): Define. (ecoff_bfd_relax_section): Don't define. * ecoff.c (ecoff_final_link_debug_accumulate): Don't read or free the debugging information if it has already been read. (ecoff_indirect_link_order): Handle _cooked_size being different from _raw_size. Don't reread the contents or the relocs if they have already been read in. * coff-mips.c (mips_howto_table): Change bitsize of PCREL16 from 18 to 16. (PCREL16_EXPANSION_ADJUSTMENT): Define. (mips_relocate_refhi): Take adjust argument. (mips_relocate_section): Handle reloc offsets stored in section used_by_bfd field. Call mips_relax_pcrel16 to handle details of expanding an out of range PCREL16. Keep trace of adjustments required by expansions. Set s and unset h when converting a reloc from undefined to section. Change handling of PC relative relocs: if against a section, they are correct in the object file, if against an external symbol they are pcrel_offset. (mips_relax_section): New function. (mips_relax_pcrel16): New function. (ecoff_bfd_relax_section): Define. * coff-alpha.c (ecoff_bfd_relax_section): Define. * ecofflink.c (bfd_ecoff_debug_accumulate): Handle adjustments built by mips_relax_section when writing out addresses. * elf32-mips.c (mips_elf_read_ecoff_info): Clear adjust field.
Diffstat (limited to 'bfd/ecofflink.c')
-rw-r--r--bfd/ecofflink.c128
1 files changed, 108 insertions, 20 deletions
diff --git a/bfd/ecofflink.c b/bfd/ecofflink.c
index a4507ea..4b14dcd 100644
--- a/bfd/ecofflink.c
+++ b/bfd/ecofflink.c
@@ -519,10 +519,17 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
hash reduces the chance that we will merge symbol
information that should not be merged. */
name = input_debug->ss + fdr.issBase + fdr.rss;
- lookup = (char *) alloca (strlen (name) + 20);
+
+ lookup = (char *) malloc (strlen (name) + 20);
+ if (lookup == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
sprintf (lookup, "%s %lx", name, fdr.csym);
fh = string_hash_lookup (&ainfo->fdr_hash, lookup, true, true);
+ free (lookup);
if (fh == (struct string_hash_entry *) NULL)
return false;
@@ -600,6 +607,22 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
else
(*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr);
+ /* Adjust the FDR address for any changes that may have been
+ made by relaxing. */
+ if (input_debug->adjust != (struct ecoff_value_adjust *) NULL)
+ {
+ bfd_vma adr;
+ struct ecoff_value_adjust *adjust;
+
+ adr = fdr.adr;
+ for (adjust = input_debug->adjust;
+ adjust != (struct ecoff_value_adjust *) NULL;
+ adjust = adjust->next)
+ if (adr >= adjust->start
+ && adr < adjust->end)
+ fdr.adr += adjust->adjust;
+ }
+
/* FIXME: It is conceivable that this FDR points to the .init or
.fini section, in which case this will not do the right
thing. */
@@ -641,6 +664,19 @@ bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
case stLabel:
case stProc:
case stStaticProc:
+ if (input_debug->adjust != (struct ecoff_value_adjust *) NULL)
+ {
+ bfd_vma value;
+ struct ecoff_value_adjust *adjust;
+
+ value = internal_sym.value;
+ for (adjust = input_debug->adjust;
+ adjust != (struct ecoff_value_adjust *) NULL;
+ adjust = adjust->next)
+ if (value >= adjust->start
+ && value < adjust->end)
+ internal_sym.value += adjust->adjust;
+ }
internal_sym.value += section_adjust[internal_sym.sc];
break;
@@ -1253,7 +1289,7 @@ ecoff_write_symhdr (abfd, debug, swap, where)
file_ptr where;
{
HDRR * const symhdr = &debug->symbolic_header;
- char *buff;
+ char *buff = NULL;
ecoff_align_debug (abfd, debug, swap);
@@ -1288,13 +1324,25 @@ ecoff_write_symhdr (abfd, debug, swap, where)
SET (cbExtOffset, iextMax, swap->external_ext_size);
#undef SET
- buff = (PTR) alloca (swap->external_hdr_size);
+ buff = (PTR) malloc (swap->external_hdr_size);
+ if (buff == NULL && swap->external_hdr_size != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+
(*swap->swap_hdr_out) (abfd, symhdr, buff);
if (bfd_write (buff, 1, swap->external_hdr_size, abfd)
!= swap->external_hdr_size)
- return false;
+ goto error_return;
+ if (buff != NULL)
+ free (buff);
return true;
+ error_return:
+ if (buff != NULL)
+ free (buff);
+ return false;
}
/* Write out the ECOFF debugging information. This function assumes
@@ -1377,10 +1425,20 @@ ecoff_write_shuffle (abfd, swap, shuffle, space)
bfd_byte *s;
i = swap->debug_align - (total & (swap->debug_align - 1));
- s = (bfd_byte *) alloca (i);
+ s = (bfd_byte *) malloc (i);
+ if (s == NULL && i != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+
memset ((PTR) s, 0, i);
if (bfd_write ((PTR) s, 1, i, abfd) != i)
- return false;
+ {
+ free (s);
+ return false;
+ }
+ free (s);
}
return true;
@@ -1399,19 +1457,24 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
file_ptr where;
{
struct accumulate *ainfo = (struct accumulate *) handle;
- PTR space;
+ PTR space = NULL;
if (! ecoff_write_symhdr (abfd, debug, swap, where))
- return false;
+ goto error_return;
- space = (PTR) alloca (ainfo->largest_file_shuffle);
+ space = (PTR) malloc (ainfo->largest_file_shuffle);
+ if (space == NULL && ainfo->largest_file_shuffle != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
if (! ecoff_write_shuffle (abfd, swap, ainfo->line, space)
|| ! ecoff_write_shuffle (abfd, swap, ainfo->pdr, space)
|| ! ecoff_write_shuffle (abfd, swap, ainfo->sym, space)
|| ! ecoff_write_shuffle (abfd, swap, ainfo->opt, space)
|| ! ecoff_write_shuffle (abfd, swap, ainfo->aux, space))
- return false;
+ goto error_return;
/* The string table is written out from the hash table if this is a
final link. */
@@ -1419,7 +1482,7 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
{
BFD_ASSERT (ainfo->ss_hash == (struct string_hash_entry *) NULL);
if (! ecoff_write_shuffle (abfd, swap, ainfo->ss, space))
- return false;
+ goto error_return;
}
else
{
@@ -1430,7 +1493,7 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
BFD_ASSERT (ainfo->ss == (struct shuffle *) NULL);
null = 0;
if (bfd_write ((PTR) &null, 1, 1, abfd) != 1)
- return false;
+ goto error_return;
total = 1;
BFD_ASSERT (ainfo->ss_hash == NULL || ainfo->ss_hash->val == 1);
for (sh = ainfo->ss_hash;
@@ -1441,7 +1504,7 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
len = strlen (sh->root.string);
if (bfd_write ((PTR) sh->root.string, 1, len + 1, abfd) != len + 1)
- return false;
+ goto error_return;
total += len + 1;
}
@@ -1451,10 +1514,19 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
bfd_byte *s;
i = swap->debug_align - (total & (swap->debug_align - 1));
- s = (bfd_byte *) alloca (i);
+ s = (bfd_byte *) malloc (i);
+ if (s == NULL && i != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
memset ((PTR) s, 0, i);
if (bfd_write ((PTR) s, 1, i, abfd) != i)
- return false;
+ {
+ free (s);
+ goto error_return;
+ }
+ free (s);
}
}
@@ -1462,7 +1534,7 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
shuffles. FIXME: They probably should be. */
if (bfd_write (debug->ssext, 1, debug->symbolic_header.issExtMax, abfd)
!= debug->symbolic_header.issExtMax)
- return false;
+ goto error_return;
if ((debug->symbolic_header.issExtMax & (swap->debug_align - 1)) != 0)
{
int i;
@@ -1470,15 +1542,24 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
i = (swap->debug_align
- (debug->symbolic_header.issExtMax & (swap->debug_align - 1)));
- s = (bfd_byte *) alloca (i);
+ s = (bfd_byte *) malloc (i);
+ if (s == NULL && i != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
memset ((PTR) s, 0, i);
if (bfd_write ((PTR) s, 1, i, abfd) != i)
- return false;
+ {
+ free (s);
+ goto error_return;
+ }
+ free (s);
}
if (! ecoff_write_shuffle (abfd, swap, ainfo->fdr, space)
|| ! ecoff_write_shuffle (abfd, swap, ainfo->rfd, space))
- return false;
+ goto error_return;
BFD_ASSERT (debug->symbolic_header.cbExtOffset == 0
|| debug->symbolic_header.cbExtOffset == bfd_tell (abfd));
@@ -1486,7 +1567,14 @@ bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
if (bfd_write (debug->external_ext, swap->external_ext_size,
debug->symbolic_header.iextMax, abfd)
!= debug->symbolic_header.iextMax * swap->external_ext_size)
- return false;
+ goto error_return;
+ if (space != NULL)
+ free (space);
return true;
+
+ error_return:
+ if (space != NULL)
+ free (space);
+ return false;
}