aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1994-09-12 21:01:19 +0000
committerIan Lance Taylor <ian@airs.com>1994-09-12 21:01:19 +0000
commit2a895595271b278bfab1041ac916688681aeedec (patch)
tree82ff7476ed510691ff14edaa5f5747a2a3237b60
parent3cd942de1e9a5e19c7132a1de400c6d3d931057b (diff)
downloadgdb-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.
-rw-r--r--bfd/ChangeLog12
-rw-r--r--bfd/cf-m68klynx.c39
-rw-r--r--bfd/coff-a29k.c26
-rw-r--r--bfd/cofflink.c162
4 files changed, 223 insertions, 16 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 9c60291..5a431aa 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 15c9915..bc6cb29 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 35e6ea3..8e6f11d 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 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;
+}