* coff-aplha.alpha.c (alpha_howto_table, alpha_finish_reloc,

alpha_ecoff_swap_reloc_{in,out}, alpha_bfd_reloc_type_lookup):
	Read and write Alpha relocs.  Can't process them yet.
	* ecoff.c (ecoff_slurp_reloc_table): Recognize new reloc sections.
	If the section does not already exist, create it.
This commit is contained in:
Ian Lance Taylor 1993-08-12 22:15:25 +00:00
parent 3f61fc966c
commit 8f46bac815
2 changed files with 20 additions and 521 deletions

View File

@ -18,6 +18,15 @@ Thu Aug 12 10:32:47 1993 David J. Mackenzie (djm@thepub.cygnus.com)
Thu Aug 12 08:30:05 1993 Ian Lance Taylor (ian@cygnus.com)
* coff-aplha.alpha.c (alpha_howto_table, alpha_finish_reloc,
alpha_ecoff_swap_reloc_{in,out}, alpha_bfd_reloc_type_lookup):
Read and write Alpha relocs. Can't process them yet.
* ecoff.c (ecoff_slurp_reloc_table): Recognize new reloc sections.
If the section does not already exist, create it.
* ecoffswap.h (ecoff_swap_pdr_{in,out}): Handle new fields defined
on the Alpha.
* libecoff.h (ecoff_backend_data): Added constructor_reloc and
finish_reloc fields.
* ecoff.c: Move MIPS reloc support from here...

View File

@ -52,30 +52,6 @@ static void ecoff_emit_aggregate PARAMS ((bfd *abfd, char *string,
CONST char *which));
static char *ecoff_type_to_string PARAMS ((bfd *abfd, union aux_ext *aux_ptr,
unsigned int indx, int bigendian));
static bfd_reloc_status_type ecoff_generic_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *section,
bfd *output_bfd));
static bfd_reloc_status_type ecoff_refhi_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *section,
bfd *output_bfd));
static bfd_reloc_status_type ecoff_reflo_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *section,
bfd *output_bfd));
static bfd_reloc_status_type ecoff_gprel_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *section,
bfd *output_bfd));
static boolean ecoff_slurp_reloc_table PARAMS ((bfd *abfd, asection *section,
asymbol **symbols));
static void ecoff_clear_output_flags PARAMS ((bfd *abfd));
@ -97,139 +73,6 @@ static unsigned int ecoff_armap_hash PARAMS ((CONST char *s,
unsigned int size,
unsigned int hlog));
/* How to process the various relocs types. */
static reloc_howto_type ecoff_howto_table[] =
{
/* Reloc type 0 is ignored. The reloc reading code ensures that
this is a reference to the .abs section, which will cause
bfd_perform_relocation to do nothing. */
HOWTO (ECOFF_R_IGNORE, /* type */
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
8, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
0, /* special_function */
"IGNORE", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
/* A 16 bit reference to a symbol, normally from a data section. */
HOWTO (ECOFF_R_REFHALF, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
ecoff_generic_reloc, /* special_function */
"REFHALF", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* A 32 bit reference to a symbol, normally from a data section. */
HOWTO (ECOFF_R_REFWORD, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
ecoff_generic_reloc, /* special_function */
"REFWORD", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
/* A 26 bit absolute jump address. */
HOWTO (ECOFF_R_JMPADDR, /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
ecoff_generic_reloc, /* special_function */
"JMPADDR", /* name */
true, /* partial_inplace */
0x3ffffff, /* src_mask */
0x3ffffff, /* dst_mask */
false), /* pcrel_offset */
/* The high 16 bits of a symbol value. Handled by the function
ecoff_refhi_reloc. */
HOWTO (ECOFF_R_REFHI, /* type */
16, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
ecoff_refhi_reloc, /* special_function */
"REFHI", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* The low 16 bits of a symbol value. */
HOWTO (ECOFF_R_REFLO, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
ecoff_reflo_reloc, /* special_function */
"REFLO", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* A reference to an offset from the gp register. Handled by the
function ecoff_gprel_reloc. */
HOWTO (ECOFF_R_GPREL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
ecoff_gprel_reloc, /* special_function */
"GPREL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* A reference to a literal using an offset from the gp register.
Handled by the function ecoff_gprel_reloc. */
HOWTO (ECOFF_R_LITERAL, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
ecoff_gprel_reloc, /* special_function */
"LITERAL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false) /* pcrel_offset */
};
#define ECOFF_HOWTO_COUNT \
(sizeof ecoff_howto_table / sizeof ecoff_howto_table[0])
/* This stuff is somewhat copied from coffcode.h. */
static asection bfd_debug_section = { "*DEBUG*" };
@ -1008,7 +851,6 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
asection *section;
arelent_chain *reloc_chain;
unsigned int bitsize;
int reloc_index;
/* Get a section with the same name as the symbol (usually
__CTOR_LIST__ or __DTOR_LIST__). FIXME: gcc uses the
@ -1040,19 +882,8 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
bfd_get_section (asym)->symbol_ptr_ptr;
reloc_chain->relent.address = section->_raw_size;
reloc_chain->relent.addend = asym->value;
bitsize = ecoff_backend (abfd)->constructor_bitsize;
switch (bitsize)
{
case 32:
reloc_index = ECOFF_R_REFWORD;
break;
case 64:
abort ();
default:
abort ();
}
reloc_chain->relent.howto = ecoff_howto_table + reloc_index;
reloc_chain->relent.howto =
ecoff_backend (abfd)->constructor_reloc;
/* Set up the constructor section to hold the reloc. */
section->flags = SEC_CONSTRUCTOR;
@ -1062,6 +893,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
based on the bitsize. These are not real sections--
they are handled specially by the linker--so the ECOFF
16 byte alignment restriction does not apply. */
bitsize = ecoff_backend (abfd)->constructor_bitsize;
section->alignment_power = 1;
while ((1 << section->alignment_power) < bitsize / 8)
++section->alignment_power;
@ -1749,292 +1581,6 @@ ecoff_print_symbol (abfd, filep, symbol, how)
}
}
/* ECOFF relocs are either against external symbols, or against
sections. If we are producing relocateable output, and the reloc
is against an external symbol, and nothing has given us any
additional addend, the resulting reloc will also be against the
same symbol. In such a case, we don't want to change anything
about the way the reloc is handled, since it will all be done at
final link time. Rather than put special case code into
bfd_perform_relocation, all the reloc types use this howto
function. It just short circuits the reloc if producing
relocateable output against an external symbol. */
static bfd_reloc_status_type
ecoff_generic_reloc (abfd,
reloc_entry,
symbol,
data,
input_section,
output_bfd)
bfd *abfd;
arelent *reloc_entry;
asymbol *symbol;
PTR data;
asection *input_section;
bfd *output_bfd;
{
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
return bfd_reloc_continue;
}
/* Do a REFHI relocation. This has to be done in combination with a
REFLO reloc, because there is a carry from the REFLO to the REFHI.
Here we just save the information we need; we do the actual
relocation when we see the REFLO. ECOFF requires that the REFLO
immediately follow the REFHI, so this ought to work. */
static bfd_byte *ecoff_refhi_addr;
static bfd_vma ecoff_refhi_addend;
static bfd_reloc_status_type
ecoff_refhi_reloc (abfd,
reloc_entry,
symbol,
data,
input_section,
output_bfd)
bfd *abfd;
arelent *reloc_entry;
asymbol *symbol;
PTR data;
asection *input_section;
bfd *output_bfd;
{
bfd_reloc_status_type ret;
bfd_vma relocation;
/* If we're relocating, and this an external symbol, we don't want
to change anything. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
ret = bfd_reloc_ok;
if (symbol->section == &bfd_und_section
&& output_bfd == (bfd *) NULL)
ret = bfd_reloc_undefined;
if (bfd_is_com_section (symbol->section))
relocation = 0;
else
relocation = symbol->value;
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
relocation += reloc_entry->addend;
if (reloc_entry->address > input_section->_cooked_size)
return bfd_reloc_outofrange;
/* Save the information, and let REFLO do the actual relocation. */
ecoff_refhi_addr = (bfd_byte *) data + reloc_entry->address;
ecoff_refhi_addend = relocation;
if (output_bfd != (bfd *) NULL)
reloc_entry->address += input_section->output_offset;
return ret;
}
/* Do a REFLO relocation. This is a straightforward 16 bit inplace
relocation; this function exists in order to do the REFHI
relocation described above. */
static bfd_reloc_status_type
ecoff_reflo_reloc (abfd,
reloc_entry,
symbol,
data,
input_section,
output_bfd)
bfd *abfd;
arelent *reloc_entry;
asymbol *symbol;
PTR data;
asection *input_section;
bfd *output_bfd;
{
if (ecoff_refhi_addr != (bfd_byte *) NULL)
{
unsigned long insn;
unsigned long val;
unsigned long vallo;
/* Do the REFHI relocation. Note that we actually don't need to
know anything about the REFLO itself, except where to find
the low 16 bits of the addend needed by the REFHI. */
insn = bfd_get_32 (abfd, ecoff_refhi_addr);
vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
& 0xffff);
val = ((insn & 0xffff) << 16) + vallo;
val += ecoff_refhi_addend;
/* The low order 16 bits are always treated as a signed value.
Therefore, a negative value in the low order bits requires an
adjustment in the high order bits. We need to make this
adjustment in two ways: once for the bits we took from the
data, and once for the bits we are putting back in to the
data. */
if ((vallo & 0x8000) != 0)
val -= 0x10000;
if ((val & 0x8000) != 0)
val += 0x10000;
insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
bfd_put_32 (abfd, insn, ecoff_refhi_addr);
ecoff_refhi_addr = (bfd_byte *) NULL;
}
/* Now do the REFLO reloc in the usual way. */
return ecoff_generic_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd);
}
/* Do a GPREL relocation. This is a 16 bit value which must become
the offset from the gp register. */
static bfd_reloc_status_type
ecoff_gprel_reloc (abfd,
reloc_entry,
symbol,
data,
input_section,
output_bfd)
bfd *abfd;
arelent *reloc_entry;
asymbol *symbol;
PTR data;
asection *input_section;
bfd *output_bfd;
{
boolean relocateable;
bfd_vma relocation;
unsigned long val;
unsigned long insn;
/* If we're relocating, and this is an external symbol with no
addend, we don't want to change anything. We will only have an
addend if this is a newly created reloc, not read from an ECOFF
file. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
}
if (output_bfd != (bfd *) NULL)
relocateable = true;
else
{
relocateable = false;
output_bfd = symbol->section->output_section->owner;
}
if (symbol->section == &bfd_und_section
&& relocateable == false)
return bfd_reloc_undefined;
/* We have to figure out the gp value, so that we can adjust the
symbol value correctly. We look up the symbol _gp in the output
BFD. If we can't find it, we're stuck. We cache it in the ECOFF
target data. We don't need to adjust the symbol value for an
external symbol if we are producing relocateable output. */
if (ecoff_data (output_bfd)->gp == 0
&& (relocateable == false
|| (symbol->flags & BSF_SECTION_SYM) != 0))
{
if (relocateable != false)
{
/* Make up a value. */
ecoff_data (output_bfd)->gp =
symbol->section->output_section->vma + 0x4000;
}
else
{
unsigned int count;
asymbol **sym;
unsigned int i;
count = bfd_get_symcount (output_bfd);
sym = bfd_get_outsymbols (output_bfd);
/* We should do something more friendly here, but we don't
have a good reloc status to return. */
if (sym == (asymbol **) NULL)
abort ();
for (i = 0; i < count; i++, sym++)
{
register CONST char *name;
name = bfd_asymbol_name (*sym);
if (*name == '_' && strcmp (name, "_gp") == 0)
{
ecoff_data (output_bfd)->gp = bfd_asymbol_value (*sym);
break;
}
}
/* We should do something more friendly here, but we don't have
a good reloc status to return. */
if (i >= count)
abort ();
}
}
if (bfd_is_com_section (symbol->section))
relocation = 0;
else
relocation = symbol->value;
relocation += symbol->section->output_section->vma;
relocation += symbol->section->output_offset;
if (reloc_entry->address > input_section->_cooked_size)
return bfd_reloc_outofrange;
insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
/* Set val to the offset into the section or symbol. */
val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
if (val & 0x8000)
val -= 0x10000;
/* Adjust val for the final section location and GP value. If we
are producing relocateable output, we don't want to do this for
an external symbol. */
if (relocateable == false
|| (symbol->flags & BSF_SECTION_SYM) != 0)
val += relocation - ecoff_data (output_bfd)->gp;
insn = (insn &~ 0xffff) | (val & 0xffff);
bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
if (relocateable != false)
reloc_entry->address += input_section->output_offset;
/* Make sure it fit in 16 bits. */
if (val >= 0x8000 && val < 0xffff8000)
return bfd_reloc_outofrange;
return bfd_reloc_ok;
}
/* Read in the relocs for a section. */
static boolean
@ -2088,9 +1634,6 @@ ecoff_slurp_reloc_table (abfd, section, symbols)
external_relocs + i * external_reloc_size,
&intern);
if (intern.r_type > ECOFF_R_LITERAL)
abort ();
if (intern.r_extern)
{
/* r_symndx is an index into the external symbols. */
@ -2117,27 +1660,26 @@ ecoff_slurp_reloc_table (abfd, section, symbols)
case RELOC_SECTION_INIT: sec_name = ".init"; break;
case RELOC_SECTION_LIT8: sec_name = ".lit8"; break;
case RELOC_SECTION_LIT4: sec_name = ".lit4"; break;
case RELOC_SECTION_XDATA: sec_name = ".xdata"; break;
case RELOC_SECTION_PDATA: sec_name = ".pdata"; break;
case RELOC_SECTION_LITA: sec_name = ".lita"; break;
case RELOC_SECTION_ABS: sec_name = ".abs"; break;
default: abort ();
}
sec = bfd_get_section_by_name (abfd, sec_name);
if (sec == (asection *) NULL)
abort ();
sec = bfd_make_section (abfd, sec_name);
rptr->sym_ptr_ptr = sec->symbol_ptr_ptr;
rptr->addend = - bfd_get_section_vma (abfd, sec);
if (intern.r_type == ECOFF_R_GPREL
|| intern.r_type == ECOFF_R_LITERAL)
rptr->addend += ecoff_data (abfd)->gp;
}
rptr->address = intern.r_vaddr - bfd_get_section_vma (abfd, section);
rptr->howto = &ecoff_howto_table[intern.r_type];
/* If the type is ECOFF_R_IGNORE, make sure this is a reference
to the absolute section so that the reloc is ignored. */
if (intern.r_type == ECOFF_R_IGNORE)
rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
/* Let the backend select the howto field and do any other
required processing. */
(*backend->finish_reloc) (abfd, &intern, rptr);
}
bfd_release (abfd, external_relocs);
@ -2189,42 +1731,6 @@ ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
return section->reloc_count;
}
/* Get the howto structure for a generic reloc type. */
CONST struct reloc_howto_struct *
ecoff_bfd_reloc_type_lookup (abfd, code)
bfd *abfd;
bfd_reloc_code_real_type code;
{
int ecoff_type;
switch (code)
{
case BFD_RELOC_16:
ecoff_type = ECOFF_R_REFHALF;
break;
case BFD_RELOC_32:
ecoff_type = ECOFF_R_REFWORD;
break;
case BFD_RELOC_MIPS_JMP:
ecoff_type = ECOFF_R_JMPADDR;
break;
case BFD_RELOC_HI16_S:
ecoff_type = ECOFF_R_REFHI;
break;
case BFD_RELOC_LO16:
ecoff_type = ECOFF_R_REFLO;
break;
case BFD_RELOC_MIPS_GPREL:
ecoff_type = ECOFF_R_GPREL;
break;
default:
return (CONST struct reloc_howto_struct *) NULL;
}
return &ecoff_howto_table[ecoff_type];
}
/* Provided a BFD, a section and an offset into the section, calculate
and return the name of the source file and the line nearest to the
@ -3713,25 +3219,9 @@ ecoff_write_object_contents (abfd)
reloc = *reloc_ptr_ptr;
sym = *reloc->sym_ptr_ptr;
/* This must be an ECOFF reloc. */
BFD_ASSERT (reloc->howto != (reloc_howto_type *) NULL
&& reloc->howto >= ecoff_howto_table
&& (reloc->howto
< (ecoff_howto_table + ECOFF_HOWTO_COUNT)));
in.r_vaddr = reloc->address + bfd_get_section_vma (abfd, current);
in.r_type = reloc->howto->type;
/* If this is a REFHI reloc, the next one must be a REFLO
reloc for the same symbol. */
BFD_ASSERT (in.r_type != ECOFF_R_REFHI
|| (reloc_ptr_ptr < reloc_end
&& (reloc_ptr_ptr[1]->howto
!= (reloc_howto_type *) NULL)
&& (reloc_ptr_ptr[1]->howto->type
== ECOFF_R_REFLO)
&& (sym == *reloc_ptr_ptr[1]->sym_ptr_ptr)));
if ((sym->flags & BSF_SECTION_SYM) == 0)
{
in.r_symndx = ecoff_get_sym_index (*reloc->sym_ptr_ptr);