aboutsummaryrefslogtreecommitdiff
path: root/bfd/coff-alpha.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/coff-alpha.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/coff-alpha.c')
-rw-r--r--bfd/coff-alpha.c44
1 files changed, 36 insertions, 8 deletions
diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c
index 64ab840..4353078 100644
--- a/bfd/coff-alpha.c
+++ b/bfd/coff-alpha.c
@@ -715,16 +715,23 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order,
bfd *input_bfd = link_order->u.indirect.section->owner;
asection *input_section = link_order->u.indirect.section;
size_t reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
- arelent **reloc_vector = (arelent **) alloca (reloc_size);
+ arelent **reloc_vector = NULL;
bfd *output_bfd = relocateable ? abfd : (bfd *) NULL;
bfd_vma gp;
boolean gp_undefined;
bfd_vma stack[RELOC_STACKSIZE];
int tos = 0;
+ reloc_vector = (arelent **) malloc (reloc_size);
+ if (reloc_vector == NULL && reloc_size != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+
if (! bfd_get_section_contents (input_bfd, input_section, data,
(file_ptr) 0, input_section->_raw_size))
- return NULL;
+ goto error_return;
/* The section size is not going to change. */
input_section->_cooked_size = input_section->_raw_size;
@@ -733,7 +740,7 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order,
if (bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector,
symbols)
== 0)
- return data;
+ goto successful_return;
/* Get the GP value for the output BFD. */
gp_undefined = false;
@@ -1080,20 +1087,20 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order,
if (! ((*link_info->callbacks->undefined_symbol)
(link_info, bfd_asymbol_name (*rel->sym_ptr_ptr),
input_bfd, input_section, rel->address)))
- return NULL;
+ goto error_return;
break;
case bfd_reloc_dangerous:
if (! ((*link_info->callbacks->reloc_dangerous)
(link_info, err, input_bfd, input_section,
rel->address)))
- return NULL;
+ goto error_return;
break;
case bfd_reloc_overflow:
if (! ((*link_info->callbacks->reloc_overflow)
(link_info, bfd_asymbol_name (*rel->sym_ptr_ptr),
rel->howto->name, rel->addend, input_bfd,
input_section, rel->address)))
- return NULL;
+ goto error_return;
break;
case bfd_reloc_outofrange:
default:
@@ -1106,7 +1113,15 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order,
if (tos != 0)
abort ();
+ successful_return:
+ if (reloc_vector != NULL)
+ free (reloc_vector);
return data;
+
+ error_return:
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+ return NULL;
}
/* Get the howto structure for a generic reloc type. */
@@ -1124,6 +1139,7 @@ alpha_bfd_reloc_type_lookup (abfd, code)
alpha_type = ALPHA_R_REFLONG;
break;
case BFD_RELOC_64:
+ case BFD_RELOC_CTOR:
alpha_type = ALPHA_R_REFQUAD;
break;
case BFD_RELOC_GPREL32:
@@ -1658,17 +1674,26 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section,
adjust the address of the reloc. */
if (! info->relocateable)
{
+ bfd_vma mask;
bfd_vma val;
if (tos == 0)
abort ();
+ /* Get the relocation mask. The separate steps and the
+ casts to bfd_vma are attempts to avoid a bug in the
+ Alpha OSF 1.3 C compiler. See reloc.c for more
+ details. */
+ mask = 1;
+ mask <<= (bfd_vma) r_size;
+ mask -= 1;
+
/* FIXME: I don't know what kind of overflow checking,
if any, should be done here. */
val = bfd_get_64 (input_bfd,
contents + r_vaddr - input_section->vma);
- val &=~ (((1 << r_size) - 1) << r_offset);
- val |= (stack[--tos] & ((1 << r_size) - 1)) << r_offset;
+ val &=~ mask << (bfd_vma) r_offset;
+ val |= (stack[--tos] & mask) << (bfd_vma) r_offset;
bfd_put_64 (input_bfd, val,
contents + r_vaddr - input_section->vma);
}
@@ -1961,6 +1986,9 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data =
#define ecoff_bfd_get_relocated_section_contents \
alpha_ecoff_get_relocated_section_contents
+/* Relaxing sections is generic. */
+#define ecoff_bfd_relax_section bfd_generic_relax_section
+
bfd_target ecoffalpha_little_vec =
{
"ecoff-littlealpha", /* name */