* 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:
parent
0e829f1854
commit
ee17481566
2 changed files with 311 additions and 5 deletions
|
@ -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
|
||||
|
|
289
bfd/xcofflink.c
289
bfd/xcofflink.c
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue