diff options
author | Ian Lance Taylor <ian@airs.com> | 1994-09-12 21:01:19 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1994-09-12 21:01:19 +0000 |
commit | 2a895595271b278bfab1041ac916688681aeedec (patch) | |
tree | 82ff7476ed510691ff14edaa5f5747a2a3237b60 /bfd/cofflink.c | |
parent | 3cd942de1e9a5e19c7132a1de400c6d3d931057b (diff) | |
download | gdb-2a895595271b278bfab1041ac916688681aeedec.zip gdb-2a895595271b278bfab1041ac916688681aeedec.tar.gz gdb-2a895595271b278bfab1041ac916688681aeedec.tar.bz2 |
* 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.
Diffstat (limited to 'bfd/cofflink.c')
-rw-r--r-- | bfd/cofflink.c | 162 |
1 files changed, 158 insertions, 4 deletions
diff --git a/bfd/cofflink.c b/bfd/cofflink.c index 31f2597..8776964 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; +} |