* xcofflink.c (XCOFF_DESCRIPTOR): Define.

(struct xcoff_link_hash_table): Add descriptor_section and
	special_sections fields.
	(_bfd_xcoff_bfd_link_hash_table_create): Initialize new fields.
	(xcoff_link_add_symbols): Set linkage section alignment.  Create
	descriptor section.  Check for magic symbol names (_text, etc.),
	and record them in special_sections if found.  Set
	XCOFF_DESCRIPTOR flag for a function descriptor, and set its
	descriptor field to point back to the function code symbol.
	(xcoff_sweep): Always mark the special descriptor_section.
	(bfd_xcoff_export_symbol): Check whether the symbol might be a
	function descriptor, and mark it if it is.
	(bfd_xcoff_size_dynamic_sections): Add new special_sections
	parameter, and fill it in.  Allocate space for the descriptor
	section.
	(xcoff_build_ldsyms): Set XCOFF_DEF_REGULAR flag when defining
	global linkage code.  If an undefined function descriptor is
	exported, arrange to define it.  Warn about any other undefined
	exported symbol.
	(_bfd_xcoff_bfd_final_link): Write out the descriptor section.
	(xcoff_write_global_symbol): Create a function descriptor when
	necessary.
	* bfd-in.h (bfd_xcoff_size_dynamic_sections): Update declaration.
	* bfd-in2.h: Rebuild.
This commit is contained in:
Ian Lance Taylor 1995-11-09 18:08:56 +00:00
parent 0e829f1854
commit ee17481566
2 changed files with 311 additions and 5 deletions

View File

@ -1,3 +1,30 @@
Thu Nov 9 13:01:31 1995 Ian Lance Taylor <ian@cygnus.com>
* xcofflink.c (XCOFF_DESCRIPTOR): Define.
(struct xcoff_link_hash_table): Add descriptor_section and
special_sections fields.
(_bfd_xcoff_bfd_link_hash_table_create): Initialize new fields.
(xcoff_link_add_symbols): Set linkage section alignment. Create
descriptor section. Check for magic symbol names (_text, etc.),
and record them in special_sections if found. Set
XCOFF_DESCRIPTOR flag for a function descriptor, and set its
descriptor field to point back to the function code symbol.
(xcoff_sweep): Always mark the special descriptor_section.
(bfd_xcoff_export_symbol): Check whether the symbol might be a
function descriptor, and mark it if it is.
(bfd_xcoff_size_dynamic_sections): Add new special_sections
parameter, and fill it in. Allocate space for the descriptor
section.
(xcoff_build_ldsyms): Set XCOFF_DEF_REGULAR flag when defining
global linkage code. If an undefined function descriptor is
exported, arrange to define it. Warn about any other undefined
exported symbol.
(_bfd_xcoff_bfd_final_link): Write out the descriptor section.
(xcoff_write_global_symbol): Create a function descriptor when
necessary.
* bfd-in.h (bfd_xcoff_size_dynamic_sections): Update declaration.
* bfd-in2.h: Rebuild.
Thu Nov 9 08:40:23 1995 Kim Knuttila <krk@cygnus.com>
* coff-ppc.c (ppc_coff_link_hash_entry): new types for hashing

View File

@ -261,7 +261,9 @@ struct xcoff_link_hash_entry
} u;
/* If this symbol is a function entry point which is called, this
field holds a pointer to the function descriptor. */
field holds a pointer to the function descriptor. If this symbol
is a function descriptor, this field holds a pointer to the
function entry point. */
struct xcoff_link_hash_entry *descriptor;
/* The .loader symbol table entry, if there is one. */
@ -296,6 +298,8 @@ struct xcoff_link_hash_entry
#define XCOFF_MARK (02000)
/* Symbol size is recorded in size_list list from hash table. */
#define XCOFF_HAS_SIZE (04000)
/* Symbol is a function descriptor. */
#define XCOFF_DESCRIPTOR (010000)
/* The storage mapping class. */
unsigned char smclas;
@ -332,6 +336,10 @@ struct xcoff_link_hash_table
linkage code. */
asection *toc_section;
/* The .ds section we use to hold function descriptors which we
create for exported symbols. */
asection *descriptor_section;
/* The list of import files. */
struct xcoff_import_file *imports;
@ -351,6 +359,9 @@ struct xcoff_link_hash_table
struct xcoff_link_hash_entry *h;
bfd_size_type size;
} *size_list;
/* Magic sections: _text, _etext, _data, _edata, _end, end. */
asection *special_sections[6];
};
/* Information we keep for each section in the output file during the
@ -627,10 +638,12 @@ _bfd_xcoff_bfd_link_hash_table_create (abfd)
memset (&ret->ldhdr, 0, sizeof (struct internal_ldhdr));
ret->linkage_section = NULL;
ret->toc_section = NULL;
ret->descriptor_section = NULL;
ret->imports = NULL;
ret->file_align = 0;
ret->textro = false;
ret->gc = false;
memset (ret->special_sections, 0, sizeof ret->special_sections);
/* The linker will always generate a full a.out header. We need to
record that fact now, before the sizeof_headers routine could be
@ -978,6 +991,7 @@ xcoff_link_add_symbols (abfd, info)
goto error_return;
xcoff_hash_table (info)->linkage_section = lsec;
lsec->flags |= SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
lsec->alignment_power = 2;
}
/* Likewise for the TOC section. */
if (xcoff_hash_table (info)->toc_section == NULL)
@ -991,6 +1005,18 @@ xcoff_link_add_symbols (abfd, info)
tsec->flags |= SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
tsec->alignment_power = 2;
}
/* Likewise for the descriptor section. */
if (xcoff_hash_table (info)->descriptor_section == NULL)
{
asection *dsec;
dsec = bfd_make_section_anyway (abfd, ".ds");
if (dsec == NULL)
goto error_return;
xcoff_hash_table (info)->descriptor_section = dsec;
dsec->flags |= SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
dsec->alignment_power = 2;
}
/* Likewise for the .debug section. */
if (xcoff_hash_table (info)->debug_section == NULL)
{
@ -1623,6 +1649,33 @@ xcoff_link_add_symbols (abfd, info)
break;
}
/* Check for magic symbol names. */
if ((smtyp == XTY_SD || smtyp == XTY_CM)
&& aux.x_csect.x_smclas != XMC_TC)
{
int i;
i = -1;
if (name[0] == '_')
{
if (strcmp (name, "_text") == 0)
i = 0;
else if (strcmp (name, "_etext") == 0)
i = 1;
else if (strcmp (name, "_data") == 0)
i = 2;
else if (strcmp (name, "_edata") == 0)
i = 3;
else if (strcmp (name, "_end") == 0)
i = 4;
}
else if (name[0] == 'e' && strcmp (name, "end") == 0)
i = 5;
if (i != -1)
xcoff_hash_table (info)->special_sections[i] = csect;
}
/* Now we have enough information to add the symbol to the
linker hash table. */
@ -1800,6 +1853,10 @@ xcoff_link_add_symbols (abfd, info)
(struct bfd_link_hash_entry **) &hds)))
goto error_return;
}
hds->flags |= XCOFF_DESCRIPTOR;
BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0
&& (h->flags & XCOFF_DESCRIPTOR) == 0);
hds->descriptor = h;
h->descriptor = hds;
}
}
@ -2250,6 +2307,7 @@ xcoff_sweep (info)
|| o == xcoff_hash_table (info)->loader_section
|| o == xcoff_hash_table (info)->linkage_section
|| o == xcoff_hash_table (info)->toc_section
|| o == xcoff_hash_table (info)->descriptor_section
|| strcmp (o->name, ".debug") == 0)
o->flags |= SEC_MARK;
else
@ -2411,10 +2469,51 @@ bfd_xcoff_export_symbol (output_bfd, info, harg, syscall)
/* FIXME: I'm not at all sure what syscall is supposed to mean, so
I'm just going to ignore it until somebody explains it. */
/* See if this is a function descriptor. It may be one even though
it is not so marked. */
if ((h->flags & XCOFF_DESCRIPTOR) == 0
&& h->root.root.string[0] != '.')
{
char *fnname;
struct xcoff_link_hash_entry *hfn;
fnname = (char *) malloc (strlen (h->root.root.string + 2));
if (fnname == NULL)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
fnname[0] = '.';
strcpy (fnname + 1, h->root.root.string);
hfn = xcoff_link_hash_lookup (xcoff_hash_table (info),
fnname, false, false, true);
free (fnname);
if (hfn != NULL
&& hfn->smclas == XMC_PR
&& (hfn->root.type == bfd_link_hash_defined
|| hfn->root.type == bfd_link_hash_defweak))
{
h->flags |= XCOFF_DESCRIPTOR;
h->descriptor = hfn;
hfn->descriptor = h;
}
}
/* Make sure we don't garbage collect this symbol. */
if (! xcoff_mark_symbol (info, h))
return false;
/* If this is a function descriptor, make sure we don't garbage
collect the associated function code. We normally don't have to
worry about this, because the descriptor will be attached to a
section with relocs, but if we are creating the descriptor
ourselves those relocs will not be visible to the mark code. */
if ((h->flags & XCOFF_DESCRIPTOR) != 0)
{
if (! xcoff_mark_symbol (info, h->descriptor))
return false;
}
return true;
}
@ -2507,7 +2606,7 @@ struct xcoff_loader_info
boolean
bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
file_align, maxstack, maxdata, gc,
modtype, textro)
modtype, textro, special_sections)
bfd *output_bfd;
struct bfd_link_info *info;
const char *libpath;
@ -2518,10 +2617,12 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
boolean gc;
int modtype;
boolean textro;
asection **special_sections;
{
struct xcoff_link_hash_entry *hentry;
asection *lsec;
struct xcoff_loader_info ldinfo;
int i;
size_t impsize, impcount;
struct xcoff_import_file *fl;
struct internal_ldhdr *ldhdr;
@ -2595,6 +2696,19 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
xcoff_hash_table (info)->gc = true;
}
/* Return special sections to the caller. */
for (i = 0; i < 6; i++)
{
asection *sec;
sec = xcoff_hash_table (info)->special_sections[i];
if (sec != NULL
&& gc
&& (sec->flags & SEC_MARK) == 0)
sec = NULL;
special_sections[i] = sec;
}
if (info->input_bfds == NULL)
{
/* I'm not sure what to do in this bizarre case. */
@ -2694,8 +2808,7 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
when the corresponding normal relocs are handled in
xcoff_link_input_bfd. */
/* Allocate space for the global linkage section and the global toc
section. */
/* Allocate space for the magic sections. */
sec = xcoff_hash_table (info)->linkage_section;
if (sec->_raw_size > 0)
{
@ -2707,6 +2820,16 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
}
}
sec = xcoff_hash_table (info)->toc_section;
if (sec->_raw_size > 0)
{
sec->contents = (bfd_byte *) bfd_zalloc (output_bfd, sec->_raw_size);
if (sec->contents == NULL)
{
bfd_set_error (bfd_error_no_memory);
goto error_return;
}
}
sec = xcoff_hash_table (info)->descriptor_section;
if (sec->_raw_size > 0)
{
sec->contents = (bfd_byte *) bfd_zalloc (output_bfd, sec->_raw_size);
@ -2877,6 +3000,7 @@ xcoff_build_ldsyms (h, p)
h->root.u.def.section = sec;
h->root.u.def.value = sec->_raw_size;
h->smclas = XMC_GL;
h->flags |= XCOFF_DEF_REGULAR;
sec->_raw_size += XCOFF_GLINK_SIZE;
/* The global linkage code requires a TOC entry for the
@ -2902,6 +3026,53 @@ xcoff_build_ldsyms (h, p)
}
}
/* If this symbol is exported, but not defined, we need to try to
define it. */
if ((h->flags & XCOFF_EXPORT) != 0
&& (h->flags & XCOFF_IMPORT) == 0
&& (h->flags & XCOFF_DEF_REGULAR) == 0
&& (h->flags & XCOFF_DEF_DYNAMIC) == 0
&& (h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak))
{
if ((h->flags & XCOFF_DESCRIPTOR) != 0
&& (h->descriptor->root.type == bfd_link_hash_defined
|| h->descriptor->root.type == bfd_link_hash_defweak))
{
asection *sec;
/* This is an undefined function descriptor associated with
a defined entry point. We can build up a function
descriptor ourselves. Believe it or not, the AIX linker
actually does this, and there are cases where we need to
do it as well. */
sec = xcoff_hash_table (ldinfo->info)->descriptor_section;
h->root.type = bfd_link_hash_defined;
h->root.u.def.section = sec;
h->root.u.def.value = sec->_raw_size;
h->smclas = XMC_DS;
h->flags |= XCOFF_DEF_REGULAR;
sec->_raw_size += 12;
/* A function descriptor uses two relocs: one for the
associated code, and one for the TOC address. */
xcoff_hash_table (ldinfo->info)->ldrel_count += 2;
sec->reloc_count += 2;
/* We handle writing out the contents of the descriptor in
xcoff_write_global_symbol. */
}
else
{
(*_bfd_error_handler)
("attempt to export undefined symbol `%s'",
h->root.root.string);
ldinfo->failed = true;
bfd_set_error (bfd_error_invalid_operation);
return false;
}
}
/* If this is still a common symbol, and it wasn't garbage
collected, we need to actually allocate space for it in the .bss
section. */
@ -3528,13 +3699,18 @@ _bfd_xcoff_bfd_final_link (abfd, info)
o->_raw_size))
goto error_return;
/* Write out the global linkage section and the toc section. */
/* Write out the magic sections. */
o = xcoff_hash_table (info)->linkage_section;
if (o->_raw_size > 0
&& ! bfd_set_section_contents (abfd, o->output_section, o->contents,
o->output_offset, o->_raw_size))
goto error_return;
o = xcoff_hash_table (info)->toc_section;
if (o->_raw_size > 0
&& ! bfd_set_section_contents (abfd, o->output_section, o->contents,
o->output_offset, o->_raw_size))
goto error_return;
o = xcoff_hash_table (info)->descriptor_section;
if (o->_raw_size > 0
&& ! bfd_set_section_contents (abfd, o->output_section, o->contents,
o->output_offset, o->_raw_size))
@ -4857,6 +5033,109 @@ xcoff_write_global_symbol (h, p)
++finfo->ldrel;
}
/* If this symbol is a specially defined function descriptor, write
it out. The first word is the address of the function code
itself, the second word is the address of the TOC, and the third
word is zero. */
if ((h->flags & XCOFF_DESCRIPTOR) != 0
&& h->root.type == bfd_link_hash_defined
&& (h->root.u.def.section
== xcoff_hash_table (finfo->info)->descriptor_section))
{
asection *sec;
asection *osec;
int oindx;
bfd_byte *p;
struct xcoff_link_hash_entry *hentry;
asection *esec;
struct internal_reloc *irel;
struct internal_ldrel ldrel;
asection *tsec;
sec = h->root.u.def.section;
osec = sec->output_section;
oindx = osec->target_index;
p = sec->contents + h->root.u.def.value;
hentry = h->descriptor;
BFD_ASSERT (hentry != NULL
&& (hentry->root.type == bfd_link_hash_defined
|| hentry->root.type == bfd_link_hash_defweak));
esec = hentry->root.u.def.section;
bfd_put_32 (output_bfd,
(esec->output_section->vma
+ esec->output_offset
+ hentry->root.u.def.value),
p);
irel = finfo->section_info[oindx].relocs + osec->reloc_count;
irel->r_vaddr = (osec->vma
+ sec->output_offset
+ h->root.u.def.value);
irel->r_symndx = esec->output_section->target_index;
irel->r_type = R_POS;
irel->r_size = 31;
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
++osec->reloc_count;
ldrel.l_vaddr = irel->r_vaddr;
if (strcmp (esec->output_section->name, ".text") == 0)
ldrel.l_symndx = 0;
else if (strcmp (esec->output_section->name, ".data") == 0)
ldrel.l_symndx = 1;
else if (strcmp (esec->output_section->name, ".bss") == 0)
ldrel.l_symndx = 2;
else
{
(*_bfd_error_handler)
("%s: loader reloc in unrecognized section `%s'",
bfd_get_filename (output_bfd),
esec->output_section->name);
bfd_set_error (bfd_error_nonrepresentable_section);
return false;
}
ldrel.l_rtype = (31 << 8) | R_POS;
ldrel.l_rsecnm = oindx;
xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
++finfo->ldrel;
bfd_put_32 (output_bfd, xcoff_data (output_bfd)->toc, p + 4);
tsec = xcoff_data (output_bfd)->toc_section;
++irel;
irel->r_vaddr = (osec->vma
+ sec->output_offset
+ h->root.u.def.value
+ 4);
irel->r_symndx = tsec->output_section->target_index;
irel->r_type = R_POS;
irel->r_size = 31;
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
++osec->reloc_count;
ldrel.l_vaddr = irel->r_vaddr;
if (strcmp (tsec->output_section->name, ".text") == 0)
ldrel.l_symndx = 0;
else if (strcmp (tsec->output_section->name, ".data") == 0)
ldrel.l_symndx = 1;
else if (strcmp (tsec->output_section->name, ".bss") == 0)
ldrel.l_symndx = 2;
else
{
(*_bfd_error_handler)
("%s: loader reloc in unrecognized section `%s'",
bfd_get_filename (output_bfd),
tsec->output_section->name);
bfd_set_error (bfd_error_nonrepresentable_section);
return false;
}
ldrel.l_rtype = (31 << 8) | R_POS;
ldrel.l_rsecnm = oindx;
xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
++finfo->ldrel;
}
if (h->indx >= 0)
return true;