* xcofflink.c (_bfd_xcoff_bfd_link_add_symbols): Look through the

members of an archive for dynamic objects with no symbols, and
	pass them directly to check_archive_element.
	(xcoff_link_check_ar_symbols): Pass dynamic objects to
	xcoff_link_check_dynamic_ar_symbols.
	(xcoff_link_check_dynamic_ar_symbols): New static function.
The above is for PR 9520.

	* coff-rs6000.c (rs6000coff_vec): Change BFD_JUMP_TABLE_DYNAMIC
	from _bfd_nodynamic to _bfd_xcoff.
	* libcoff-in.h (_bfd_xcoff_get_dynamic_symtab_upper_bound):
	Declare.
	(_bfd_xcoff_canonicalize_dynamic_symtab): Declare.
	(_bfd_xcoff_get_dynamic_reloc_upper_bound): Declare.
	(_bfd_xcoff_canonicalize_dynamic_reloc): Declare.
	* libcoff.h: Rebuild.
	* xcofflink.c (xcoff_swap_ldrel_in): New static function.
	(xcoff_get_section_contents): New static function.
	(_bfd_xcoff_get_dynamic_symtab_upper_bound): New function.
	(_bfd_xcoff_canonicalize_dynamic_symtab): New function.
	(_bfd_xcoff_get_dynamic_reloc_upper_bound): New function.
	(xcoff_dynamic_reloc): New static variable.
	(_bfd_xcoff_canonicalize_dynamic_reloc): New function.
	(xcoff_link_add_dynamic_symbols): Use xcoff_get_section_contents.
This commit is contained in:
Ian Lance Taylor 1996-04-24 18:10:46 +00:00
parent 116bf30f41
commit f5d6548535
4 changed files with 506 additions and 24 deletions

View File

@ -1,3 +1,35 @@
Wed Apr 24 14:04:07 1996 Ian Lance Taylor <ian@cygnus.com>
* xcofflink.c (_bfd_xcoff_bfd_link_add_symbols): Look through the
members of an archive for dynamic objects with no symbols, and
pass them directly to check_archive_element.
(xcoff_link_check_ar_symbols): Pass dynamic objects to
xcoff_link_check_dynamic_ar_symbols.
(xcoff_link_check_dynamic_ar_symbols): New static function.
* coff-rs6000.c (rs6000coff_vec): Change BFD_JUMP_TABLE_DYNAMIC
from _bfd_nodynamic to _bfd_xcoff.
* libcoff-in.h (_bfd_xcoff_get_dynamic_symtab_upper_bound):
Declare.
(_bfd_xcoff_canonicalize_dynamic_symtab): Declare.
(_bfd_xcoff_get_dynamic_reloc_upper_bound): Declare.
(_bfd_xcoff_canonicalize_dynamic_reloc): Declare.
* libcoff.h: Rebuild.
* xcofflink.c (xcoff_swap_ldrel_in): New static function.
(xcoff_get_section_contents): New static function.
(_bfd_xcoff_get_dynamic_symtab_upper_bound): New function.
(_bfd_xcoff_canonicalize_dynamic_symtab): New function.
(_bfd_xcoff_get_dynamic_reloc_upper_bound): New function.
(xcoff_dynamic_reloc): New static variable.
(_bfd_xcoff_canonicalize_dynamic_reloc): New function.
(xcoff_link_add_dynamic_symbols): Use xcoff_get_section_contents.
Tue Apr 23 12:48:42 1996 Ian Lance Taylor <ian@cygnus.com>
* coff-sparc.c (bfd_coff_generic_reloc): Return bfd_reloc_ok even
if reloc_entry->addend is not 0.
(CALC_ADDEND): Just set the addend to reloc.r_offset.
Mon Apr 22 18:29:01 1996 Doug Evans <dje@canuck.cygnus.com>
* elf32-sparc.c (_bfd_sparc_elf_howto_table): Fix spelling of

View File

@ -177,6 +177,8 @@ struct coff_section_tdata
unsigned int i;
const char *function;
int line_base;
/* A pointer used for .stab linking optimizations. */
PTR stab_info;
/* Available for individual backends. */
PTR tdata;
};
@ -236,6 +238,8 @@ struct coff_link_hash_entry
struct coff_link_hash_table
{
struct bfd_link_hash_table root;
/* A pointer to information used to link stabs in sections. */
PTR stab_info;
};
/* Look up an entry in a COFF linker hash table. */
@ -473,6 +477,12 @@ extern boolean _bfd_coff_reloc_link_order
/* Functions in xcofflink.c. */
extern long _bfd_xcoff_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
extern long _bfd_xcoff_canonicalize_dynamic_symtab
PARAMS ((bfd *, asymbol **));
extern long _bfd_xcoff_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
extern long _bfd_xcoff_canonicalize_dynamic_reloc
PARAMS ((bfd *, arelent **, asymbol **));
extern struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create
PARAMS ((bfd *));
extern boolean _bfd_xcoff_bfd_link_add_symbols

View File

@ -177,6 +177,8 @@ struct coff_section_tdata
unsigned int i;
const char *function;
int line_base;
/* A pointer used for .stab linking optimizations. */
PTR stab_info;
/* Available for individual backends. */
PTR tdata;
};
@ -236,6 +238,8 @@ struct coff_link_hash_entry
struct coff_link_hash_table
{
struct bfd_link_hash_table root;
/* A pointer to information used to link stabs in sections. */
PTR stab_info;
};
/* Look up an entry in a COFF linker hash table. */
@ -473,6 +477,12 @@ extern boolean _bfd_coff_reloc_link_order
/* Functions in xcofflink.c. */
extern long _bfd_xcoff_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
extern long _bfd_xcoff_canonicalize_dynamic_symtab
PARAMS ((bfd *, asymbol **));
extern long _bfd_xcoff_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
extern long _bfd_xcoff_canonicalize_dynamic_reloc
PARAMS ((bfd *, arelent **, asymbol **));
extern struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create
PARAMS ((bfd *));
extern boolean _bfd_xcoff_bfd_link_add_symbols

View File

@ -435,6 +435,8 @@ static void xcoff_swap_ldsym_in
PARAMS ((bfd *, const struct external_ldsym *, struct internal_ldsym *));
static void xcoff_swap_ldsym_out
PARAMS ((bfd *, const struct internal_ldsym *, struct external_ldsym *));
static void xcoff_swap_ldrel_in
PARAMS ((bfd *, const struct external_ldrel *, struct internal_ldrel *));
static void xcoff_swap_ldrel_out
PARAMS ((bfd *, const struct internal_ldrel *, struct external_ldrel *));
static struct bfd_hash_entry *xcoff_link_hash_newfunc
@ -448,6 +450,8 @@ static boolean xcoff_link_check_archive_element
PARAMS ((bfd *, struct bfd_link_info *, boolean *));
static boolean xcoff_link_check_ar_symbols
PARAMS ((bfd *, struct bfd_link_info *, boolean *));
static boolean xcoff_link_check_dynamic_ar_symbols
PARAMS ((bfd *, struct bfd_link_info *, boolean *));
static bfd_size_type xcoff_find_reloc
PARAMS ((struct internal_reloc *, bfd_size_type, bfd_vma));
static boolean xcoff_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *));
@ -553,7 +557,19 @@ xcoff_swap_ldsym_out (abfd, src, dst)
bfd_put_32 (abfd, src->l_parm, dst->l_parm);
}
/* As it happens, we never need to swap in the ldrel structure. */
/* Swap in the ldrel structure. */
static void
xcoff_swap_ldrel_in (abfd, src, dst)
bfd *abfd;
const struct external_ldrel *src;
struct internal_ldrel *dst;
{
dst->l_vaddr = bfd_get_32 (abfd, src->l_vaddr);
dst->l_symndx = bfd_get_32 (abfd, src->l_symndx);
dst->l_rtype = bfd_get_16 (abfd, src->l_rtype);
dst->l_rsecnm = bfd_get_16 (abfd, src->l_rsecnm);
}
/* Swap out the ldrel structure. */
@ -569,6 +585,316 @@ xcoff_swap_ldrel_out (abfd, src, dst)
bfd_put_16 (abfd, src->l_rsecnm, dst->l_rsecnm);
}
/* Routines to read XCOFF dynamic information. This don't really
belong here, but we already have the ldsym manipulation routines
here. */
/* Read the contents of a section. */
static boolean
xcoff_get_section_contents (abfd, sec)
bfd *abfd;
asection *sec;
{
if (coff_section_data (abfd, sec) == NULL)
{
sec->used_by_bfd = bfd_zalloc (abfd,
sizeof (struct coff_section_tdata));
if (sec->used_by_bfd == NULL)
return false;
}
if (coff_section_data (abfd, sec)->contents == NULL)
{
coff_section_data (abfd, sec)->contents = bfd_malloc (sec->_raw_size);
if (coff_section_data (abfd, sec)->contents == NULL)
return false;
if (! bfd_get_section_contents (abfd, sec,
coff_section_data (abfd, sec)->contents,
(file_ptr) 0, sec->_raw_size))
return false;
}
return true;
}
/* Get the size required to hold the dynamic symbols. */
long
_bfd_xcoff_get_dynamic_symtab_upper_bound (abfd)
bfd *abfd;
{
asection *lsec;
bfd_byte *contents;
struct internal_ldhdr ldhdr;
if ((abfd->flags & DYNAMIC) == 0)
{
bfd_set_error (bfd_error_invalid_operation);
return -1;
}
lsec = bfd_get_section_by_name (abfd, ".loader");
if (lsec == NULL)
{
bfd_set_error (bfd_error_no_symbols);
return -1;
}
if (! xcoff_get_section_contents (abfd, lsec))
return -1;
contents = coff_section_data (abfd, lsec)->contents;
xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
return (ldhdr.l_nsyms + 1) * sizeof (asymbol *);
}
/* Get the dynamic symbols. */
long
_bfd_xcoff_canonicalize_dynamic_symtab (abfd, psyms)
bfd *abfd;
asymbol **psyms;
{
asection *lsec;
bfd_byte *contents;
struct internal_ldhdr ldhdr;
const char *strings;
struct external_ldsym *elsym, *elsymend;
coff_symbol_type *symbuf;
if ((abfd->flags & DYNAMIC) == 0)
{
bfd_set_error (bfd_error_invalid_operation);
return -1;
}
lsec = bfd_get_section_by_name (abfd, ".loader");
if (lsec == NULL)
{
bfd_set_error (bfd_error_no_symbols);
return -1;
}
if (! xcoff_get_section_contents (abfd, lsec))
return -1;
contents = coff_section_data (abfd, lsec)->contents;
coff_section_data (abfd, lsec)->keep_contents = true;
xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
strings = (char *) contents + ldhdr.l_stoff;
symbuf = ((coff_symbol_type *)
bfd_zalloc (abfd, ldhdr.l_nsyms * sizeof (coff_symbol_type)));
if (symbuf == NULL)
return -1;
elsym = (struct external_ldsym *) (contents + LDHDRSZ);
elsymend = elsym + ldhdr.l_nsyms;
for (; elsym < elsymend; elsym++, symbuf++, psyms++)
{
struct internal_ldsym ldsym;
xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
symbuf->symbol.the_bfd = abfd;
if (ldsym._l._l_l._l_zeroes == 0)
symbuf->symbol.name = strings + ldsym._l._l_l._l_offset;
else
{
int i;
for (i = 0; i < SYMNMLEN; i++)
if (ldsym._l._l_name[i] == '\0')
break;
if (i < SYMNMLEN)
symbuf->symbol.name = elsym->_l._l_name;
else
{
char *c;
c = bfd_alloc (abfd, SYMNMLEN + 1);
if (c == NULL)
return -1;
memcpy (c, ldsym._l._l_name, SYMNMLEN);
c[SYMNMLEN] = '\0';
symbuf->symbol.name = c;
}
}
if (ldsym.l_smclas == XMC_XO)
symbuf->symbol.section = bfd_abs_section_ptr;
else
symbuf->symbol.section = coff_section_from_bfd_index (abfd,
ldsym.l_scnum);
symbuf->symbol.value = ldsym.l_value - symbuf->symbol.section->vma;
symbuf->symbol.flags = BSF_NO_FLAGS;
if ((ldsym.l_smtype & L_EXPORT) != 0)
symbuf->symbol.flags |= BSF_GLOBAL;
/* FIXME: We have no way to record the other information stored
with the loader symbol. */
*psyms = (asymbol *) symbuf;
}
*psyms = NULL;
return ldhdr.l_nsyms;
}
/* Get the size required to hold the dynamic relocs. */
long
_bfd_xcoff_get_dynamic_reloc_upper_bound (abfd)
bfd *abfd;
{
asection *lsec;
bfd_byte *contents;
struct internal_ldhdr ldhdr;
if ((abfd->flags & DYNAMIC) == 0)
{
bfd_set_error (bfd_error_invalid_operation);
return -1;
}
lsec = bfd_get_section_by_name (abfd, ".loader");
if (lsec == NULL)
{
bfd_set_error (bfd_error_no_symbols);
return -1;
}
if (! xcoff_get_section_contents (abfd, lsec))
return -1;
contents = coff_section_data (abfd, lsec)->contents;
xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
return (ldhdr.l_nreloc + 1) * sizeof (arelent *);
}
/* The typical dynamic reloc. */
static reloc_howto_type xcoff_dynamic_reloc =
HOWTO (0, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_POS", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false); /* pcrel_offset */
/* Get the dynamic relocs. */
long
_bfd_xcoff_canonicalize_dynamic_reloc (abfd, prelocs, syms)
bfd *abfd;
arelent **prelocs;
asymbol **syms;
{
asection *lsec;
bfd_byte *contents;
struct internal_ldhdr ldhdr;
arelent *relbuf;
struct external_ldrel *elrel, *elrelend;
if ((abfd->flags & DYNAMIC) == 0)
{
bfd_set_error (bfd_error_invalid_operation);
return -1;
}
lsec = bfd_get_section_by_name (abfd, ".loader");
if (lsec == NULL)
{
bfd_set_error (bfd_error_no_symbols);
return -1;
}
if (! xcoff_get_section_contents (abfd, lsec))
return -1;
contents = coff_section_data (abfd, lsec)->contents;
xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
relbuf = (arelent *) bfd_alloc (abfd, ldhdr.l_nreloc * sizeof (arelent));
if (relbuf == NULL)
return -1;
elrel = ((struct external_ldrel *)
(contents + LDHDRSZ + ldhdr.l_nsyms * LDSYMSZ));
elrelend = elrel + ldhdr.l_nreloc;
for (; elrel < elrelend; elrel++, relbuf++, prelocs++)
{
struct internal_ldrel ldrel;
xcoff_swap_ldrel_in (abfd, elrel, &ldrel);
if (ldrel.l_symndx >= 3)
relbuf->sym_ptr_ptr = syms + (ldrel.l_symndx - 3);
else
{
const char *name;
asection *sec;
switch (ldrel.l_symndx)
{
case 0:
name = ".text";
break;
case 1:
name = ".data";
break;
case 2:
name = ".bss";
break;
default:
abort ();
break;
}
sec = bfd_get_section_by_name (abfd, name);
if (sec == NULL)
{
bfd_set_error (bfd_error_bad_value);
return -1;
}
relbuf->sym_ptr_ptr = sec->symbol_ptr_ptr;
}
relbuf->address = ldrel.l_vaddr;
relbuf->addend = 0;
/* Most dynamic relocs have the same type. FIXME: This is only
correct if ldrel.l_rtype == 0. In other cases, we should use
a different howto. */
relbuf->howto = &xcoff_dynamic_reloc;
/* FIXME: We have no way to record the l_rsecnm field. */
*prelocs = relbuf;
}
*prelocs = NULL;
return ldhdr.l_nreloc;
}
/* Routine to create an entry in an XCOFF link hash table. */
static struct bfd_hash_entry *
@ -736,8 +1062,34 @@ _bfd_xcoff_bfd_link_add_symbols (abfd, info)
case bfd_object:
return xcoff_link_add_object_symbols (abfd, info);
case bfd_archive:
return (_bfd_generic_link_add_archive_symbols
(abfd, info, xcoff_link_check_archive_element));
/* We need to look through the archive for stripped dynamic
objects, because they will not appear in the archive map even
though they should, perhaps, be included. */
{
bfd *member;
member = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
while (member != NULL)
{
if (bfd_check_format (member, bfd_object)
&& (member->flags & DYNAMIC) != 0
&& (member->flags & HAS_SYMS) == 0)
{
boolean needed;
if (! xcoff_link_check_archive_element (member, info, &needed))
return false;
if (needed)
member->archive_pass = -1;
}
member = bfd_openr_next_archived_file (abfd, member);
}
/* Now do the usual search. */
return (_bfd_generic_link_add_archive_symbols
(abfd, info, xcoff_link_check_archive_element));
}
default:
bfd_set_error (bfd_error_wrong_format);
return false;
@ -810,6 +1162,11 @@ xcoff_link_check_ar_symbols (abfd, info, pneeded)
*pneeded = false;
if ((abfd->flags & DYNAMIC) != 0
&& ! info->static_link
&& info->hash->creator == abfd->xvec)
return xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded);
symesz = bfd_coff_symesz (abfd);
esym = (bfd_byte *) obj_coff_external_syms (abfd);
esym_end = esym + obj_raw_syment_count (abfd) * symesz;
@ -855,6 +1212,87 @@ xcoff_link_check_ar_symbols (abfd, info, pneeded)
return true;
}
/* Look through the loader symbols to see if this dynamic object
should be included in the link. The native linker uses the loader
symbols, not the normal symbol table, so we do too. */
static boolean
xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded)
bfd *abfd;
struct bfd_link_info *info;
boolean *pneeded;
{
asection *lsec;
bfd_byte *buf;
struct internal_ldhdr ldhdr;
const char *strings;
struct external_ldsym *elsym, *elsymend;
*pneeded = false;
lsec = bfd_get_section_by_name (abfd, ".loader");
if (lsec == NULL)
{
/* There are no symbols, so don't try to include it. */
return true;
}
if (! xcoff_get_section_contents (abfd, lsec))
return false;
buf = coff_section_data (abfd, lsec)->contents;
xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) buf, &ldhdr);
strings = (char *) buf + ldhdr.l_stoff;
elsym = (struct external_ldsym *) (buf + LDHDRSZ);
elsymend = elsym + ldhdr.l_nsyms;
for (; elsym < elsymend; elsym++)
{
struct internal_ldsym ldsym;
char nambuf[SYMNMLEN + 1];
const char *name;
struct bfd_link_hash_entry *h;
xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
/* We are only interested in exported symbols. */
if ((ldsym.l_smtype & L_EXPORT) == 0)
continue;
if (ldsym._l._l_l._l_zeroes == 0)
name = strings + ldsym._l._l_l._l_offset;
else
{
memcpy (nambuf, ldsym._l._l_name, SYMNMLEN);
nambuf[SYMNMLEN] = '\0';
name = nambuf;
}
h = bfd_link_hash_lookup (info->hash, name, false, false, true);
/* We are only interested in symbols that are currently
undefined. */
if (h != NULL && h->type == bfd_link_hash_undefined)
{
if (! (*info->callbacks->add_archive_element) (info, abfd, name))
return false;
*pneeded = true;
return true;
}
}
/* We do not need this shared object. */
if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
{
free (coff_section_data (abfd, lsec)->contents);
coff_section_data (abfd, lsec)->contents = NULL;
}
return true;
}
/* Returns the index of reloc in RELOCS with the least address greater
than or equal to ADDRESS. The relocs are sorted by address. */
@ -1903,7 +2341,7 @@ xcoff_link_add_dynamic_symbols (abfd, info)
struct bfd_link_info *info;
{
asection *lsec;
bfd_byte *buf = NULL;
bfd_byte *buf;
struct internal_ldhdr ldhdr;
const char *strings;
struct external_ldsym *elsym, *elsymend;
@ -1922,7 +2360,7 @@ xcoff_link_add_dynamic_symbols (abfd, info)
("%s: XCOFF shared object when not producing XCOFF output",
bfd_get_filename (abfd));
bfd_set_error (bfd_error_invalid_operation);
goto error_return;
return false;
}
/* The symbols we use from a dynamic object are not the symbols in
@ -1943,16 +2381,12 @@ xcoff_link_add_dynamic_symbols (abfd, info)
("%s: dynamic object with no .loader section",
bfd_get_filename (abfd));
bfd_set_error (bfd_error_no_symbols);
goto error_return;
return false;
}
buf = (bfd_byte *) bfd_malloc (lsec->_raw_size);
if (buf == NULL && lsec->_raw_size > 0)
goto error_return;
if (! bfd_get_section_contents (abfd, lsec, (PTR) buf, (file_ptr) 0,
lsec->_raw_size))
goto error_return;
if (! xcoff_get_section_contents (abfd, lsec))
return false;
buf = coff_section_data (abfd, lsec)->contents;
/* Remove the sections from this object, so that they do not get
included in the link. */
@ -1995,7 +2429,7 @@ xcoff_link_add_dynamic_symbols (abfd, info)
h = xcoff_link_hash_lookup (xcoff_hash_table (info), name, true,
true, true);
if (h == NULL)
goto error_return;
return false;
h->flags |= XCOFF_DEF_DYNAMIC;
@ -2036,10 +2470,10 @@ xcoff_link_add_dynamic_symbols (abfd, info)
}
}
if (buf != NULL)
if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
{
free (buf);
buf = NULL;
free (coff_section_data (abfd, lsec)->contents);
coff_section_data (abfd, lsec)->contents = NULL;
}
/* Record this file in the import files. */
@ -2047,7 +2481,7 @@ xcoff_link_add_dynamic_symbols (abfd, info)
n = ((struct xcoff_import_file *)
bfd_alloc (abfd, sizeof (struct xcoff_import_file)));
if (n == NULL)
goto error_return;
return false;
n->next = NULL;
/* For some reason, the path entry in the import file list for a
@ -2081,11 +2515,6 @@ xcoff_link_add_dynamic_symbols (abfd, info)
xcoff_data (abfd)->import_file_id = c;
return true;
error_return:
if (buf != NULL)
free (buf);
return false;
}
/* Routines that are called after all the input files have been
@ -4350,7 +4779,8 @@ xcoff_link_input_bfd (finfo, input_bfd)
if (ISFCN (isymp->n_type)
|| ISTAG (isymp->n_sclass)
|| isymp->n_sclass == C_BLOCK)
|| isymp->n_sclass == C_BLOCK
|| isymp->n_sclass == C_FCN)
{
indx = aux.x_sym.x_fcnary.x_fcn.x_endndx.l;
if (indx > 0