From 2a895595271b278bfab1041ac916688681aeedec Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 12 Sep 1994 21:01:19 +0000 Subject: [PATCH] * 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. --- bfd/ChangeLog | 12 ++++ bfd/cf-m68klynx.c | 39 +++++++++-- bfd/coff-a29k.c | 26 +++++--- bfd/cofflink.c | 162 ++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 223 insertions(+), 16 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9c60291693..5a431aae8a 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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. diff --git a/bfd/cf-m68klynx.c b/bfd/cf-m68klynx.c index 15c9915b88..bc6cb293f4 100644 --- a/bfd/cf-m68klynx.c +++ b/bfd/cf-m68klynx.c @@ -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 diff --git a/bfd/coff-a29k.c b/bfd/coff-a29k.c index 35e6ea353d..8e6f11dd32 100644 --- a/bfd/coff-a29k.c +++ b/bfd/coff-a29k.c @@ -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*"; diff --git a/bfd/cofflink.c b/bfd/cofflink.c index 31f2597e45..87769648c2 100644 --- a/bfd/cofflink.c +++ b/bfd/cofflink.c @@ -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; +} -- 2.34.1