* cofflink.c (coff_link_input_bfd): If r_symndx is -1, don't

change it.
	(_bfd_coff_generic_relocate_section): If r_symndx is -1, it is an
	absolute reloc.  Don't dump core using r_symndx as an array index.
	* cf-m68klynx.c (coff_bfd_link_add_symbols): Define.
	(lynx_link_add_symbols): New static function (copy of function in
	coff-i386.c).
	(coff_m68k_lynxrtype_to_howto): sym argument may be NULL.
	* coff-i386.c (coff_i386_rtype_to_howto): Likewise.
	* coff-a29k.c (coff_a29k_relocate_section): Handle an r_symndx
	value of -1, meaning an absolute reloc.
This commit is contained in:
Ian Lance Taylor 1994-09-12 21:01:19 +00:00
parent 3cd942de1e
commit 2a89559527
4 changed files with 223 additions and 16 deletions

View File

@ -1,5 +1,17 @@
Mon Sep 12 11:43:08 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
* cofflink.c (coff_link_input_bfd): If r_symndx is -1, don't
change it.
(_bfd_coff_generic_relocate_section): If r_symndx is -1, it is an
absolute reloc. Don't dump core using r_symndx as an array index.
* cf-m68klynx.c (coff_bfd_link_add_symbols): Define.
(lynx_link_add_symbols): New static function (copy of function in
coff-i386.c).
(coff_m68k_lynxrtype_to_howto): sym argument may be NULL.
* coff-i386.c (coff_i386_rtype_to_howto): Likewise.
* coff-a29k.c (coff_a29k_relocate_section): Handle an r_symndx
value of -1, meaning an absolute reloc.
* ctor.c: Remove; obsolete.
* Makefile.in: Rebuild dependencies.
(BFD_LIBS): Remove ctor.o.

View File

@ -43,6 +43,7 @@ struct internal_syment;
static bfd_reloc_status_type _bfd_m68klynx_special_fn
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static boolean lynx_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *));
static const struct reloc_howto_struct *coff_m68k_lynx_rtype_to_howto
PARAMS ((bfd *, asection *, struct internal_reloc *,
struct coff_link_hash_entry *, struct internal_syment *,
@ -175,14 +176,44 @@ _bfd_m68klynx_special_fn (abfd, reloc_entry, symbol, data, input_section,
cache_ptr->addend += asect->vma; \
}
#define coff_bfd_link_add_symbols lynx_link_add_symbols
#define coff_rtype_to_howto coff_m68k_lynx_rtype_to_howto
#include "coff-m68k.c"
/* On Lynx, we may have a COFF archive which contains a.out elements.
This screws up the COFF linker, which expects that any archive it
gets contains COFF elements. We override the add_symbols function
to check for this case. */
static boolean
lynx_link_add_symbols (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
if (bfd_get_format (abfd) == bfd_archive)
{
bfd *first;
first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
if (first == NULL)
return false;
if (! bfd_check_format (first, bfd_object))
return false;
if (bfd_get_flavour (first) != bfd_target_coff_flavour)
{
/* Treat the archive as though it were actually of the
flavour of its first element. This ought to work,
since the archive support is fairly generic. */
return (*first->xvec->_bfd_link_add_symbols) (abfd, info);
}
}
return _bfd_coff_link_add_symbols (abfd, info);
}
/* coff-m68k.c uses the special COFF backend linker. We need to
adjust common symbols. FIXME: We may able to get rid of
CALC_ADDEND and _bfd_m68klynx_special_fn. However, they may still
be used by gas.
adjust common symbols.
We can't define this function until after we have included
coff-m68k.c, because it uses RTYPE2HOWTO. */
@ -204,7 +235,7 @@ coff_m68k_lynx_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
howto = relent.howto;
if (sym->n_scnum == 0 && sym->n_value != 0)
if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
{
/* This is a common symbol. The section contents include the
size (sym->n_value) as an addend. The relocate_section

View File

@ -353,7 +353,10 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
symndx = rel->r_symndx;
loc = contents + rel->r_vaddr - input_section->vma;
h = obj_coff_sym_hashes (input_bfd)[symndx];
if (symndx == -1)
h = NULL;
else
h = obj_coff_sym_hashes (input_bfd)[symndx];
sym = NULL;
sec = NULL;
@ -366,12 +369,17 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
{
if (h == NULL)
{
sym = syms + symndx;
sec = sections[symndx];
val = (sec->output_section->vma
+ sec->output_offset
+ sym->n_value
- sec->vma);
if (symndx == -1)
sec = bfd_abs_section_ptr;
else
{
sym = syms + symndx;
sec = sections[symndx];
val = (sec->output_section->vma
+ sec->output_offset
+ sym->n_value
- sec->vma);
}
}
else
{
@ -497,7 +505,9 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
const char *name;
char buf[SYMNMLEN + 1];
if (h != NULL)
if (symndx == -1)
name = "*ABS*";
else if (h != NULL)
name = h->root.root.string;
else if (sym == NULL)
name = "*unknown*";

View File

@ -695,15 +695,17 @@ _bfd_coff_final_link (abfd, info)
{
unsigned int i;
/* We use section_count + 1, rather than section_count, because
the target_index fields are 1 based. */
finfo.section_info = ((struct coff_link_section_info *)
malloc (abfd->section_count
malloc ((abfd->section_count + 1)
* sizeof (struct coff_link_section_info)));
if (finfo.section_info == NULL)
{
bfd_set_error (bfd_error_no_memory);
goto error_return;
}
for (i = 0; i < abfd->section_count; i++)
for (i = 0; i <= abfd->section_count; i++)
{
finfo.section_info[i].relocs = NULL;
finfo.section_info[i].rel_hashes = NULL;
@ -1122,7 +1124,16 @@ coff_link_input_bfd (finfo, input_bfd)
the symbol. */
isym = *isymp;
*secpp = coff_section_from_bfd_index (input_bfd, isym.n_scnum);
if (isym.n_scnum != 0)
*secpp = coff_section_from_bfd_index (input_bfd, isym.n_scnum);
else
{
if (isym.n_value == 0)
*secpp = bfd_und_section_ptr;
else
*secpp = bfd_com_section_ptr;
}
*indexp = -1;
skip = false;
@ -1647,7 +1658,8 @@ coff_link_input_bfd (finfo, input_bfd)
irel = internal_relocs;
irelend = irel + o->reloc_count;
rel_hash = finfo->section_info[target_index].rel_hashes;
rel_hash = (finfo->section_info[target_index].rel_hashes
+ o->output_section->reloc_count);
for (; irel < irelend; irel++, rel_hash++)
{
struct coff_link_hash_entry *h;
@ -1658,6 +1670,9 @@ coff_link_input_bfd (finfo, input_bfd)
irel->r_vaddr += offset;
if (irel->r_symndx == -1)
continue;
h = obj_coff_sym_hashes (input_bfd)[irel->r_symndx];
if (h != NULL)
{
@ -2004,3 +2019,142 @@ coff_reloc_link_order (output_bfd, finfo, output_section, link_order)
return true;
}
/* A basic reloc handling routine which may be used by processors with
simple relocs. */
boolean
_bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
input_section, contents, relocs, syms,
sections)
bfd *output_bfd;
struct bfd_link_info *info;
bfd *input_bfd;
asection *input_section;
bfd_byte *contents;
struct internal_reloc *relocs;
struct internal_syment *syms;
asection **sections;
{
struct internal_reloc *rel;
struct internal_reloc *relend;
rel = relocs;
relend = rel + input_section->reloc_count;
for (; rel < relend; rel++)
{
long symndx;
struct coff_link_hash_entry *h;
struct internal_syment *sym;
bfd_vma addend;
bfd_vma val;
const reloc_howto_type *howto;
bfd_reloc_status_type rstat;
symndx = rel->r_symndx;
if (symndx == -1)
{
h = NULL;
sym = NULL;
}
else
{
h = obj_coff_sym_hashes (input_bfd)[symndx];
sym = syms + symndx;
}
/* COFF treats common symbols in one of two ways. Either the
size of the symbol is included in the section contents, or it
is not. We assume that the size is not included, and force
the rtype_to_howto function to adjust the addend as needed. */
if (sym != NULL && sym->n_scnum != 0)
addend = - sym->n_value;
else
addend = 0;
howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
sym, &addend);
if (howto == NULL)
return false;
val = 0;
if (h == NULL)
{
asection *sec;
if (symndx == -1)
{
sec = bfd_abs_section_ptr;
val = 0;
}
else
{
sec = sections[symndx];
val = (sec->output_section->vma
+ sec->output_offset
+ sym->n_value
- sec->vma);
}
}
else
{
if (h->root.type == bfd_link_hash_defined)
{
asection *sec;
sec = h->root.u.def.section;
val = (h->root.u.def.value
+ sec->output_section->vma
+ sec->output_offset);
}
else if (! info->relocateable)
{
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd, input_section,
rel->r_vaddr - input_section->vma)))
return false;
}
}
rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
contents,
rel->r_vaddr - input_section->vma,
val, addend);
switch (rstat)
{
default:
abort ();
case bfd_reloc_ok:
break;
case bfd_reloc_overflow:
{
const char *name;
char buf[SYMNMLEN + 1];
if (symndx == -1)
name = "*ABS*";
else if (h != NULL)
name = h->root.root.string;
else if (sym->_n._n_n._n_zeroes == 0
&& sym->_n._n_n._n_offset != 0)
name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
else
{
strncpy (buf, sym->_n._n_name, SYMNMLEN);
buf[SYMNMLEN] = '\0';
name = buf;
}
if (! ((*info->callbacks->reloc_overflow)
(info, name, howto->name, (bfd_vma) 0, input_bfd,
input_section, rel->r_vaddr - input_section->vma)))
return false;
}
}
}
return true;
}