mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-01 13:26:47 +08:00
* xcofflink.c: Numerous changes to get closer to a working XCOFF
linker. * libcoff-in.h (struct xcoff_tdata): Add full_aouthdr, toc_section, and entry_section fields. (struct xcoff_section_tdata): Remove ldrel_count field. * libcoff.h: Rebuild. * coffcode.h (coff_mkobject_hook): Initialize new xcoff_data fields. (coff_compute_section_file_positions): If RS6000COFF_C, generate full a.out header if full_aouthdr is set in xcoff_data. (coff_write_object_contents): Likewise. Set o_snentry and o_sntoc based on sections stored in xcoff_data. * coff-rs6000.c (xcoff_copy_private_bfd_data): Copy new xcoff_data fields. * coffgen.c (coff_get_symbol_info): If fix_value is set, fix the value stored in ret rather than returning a pointer value.
This commit is contained in:
parent
328e5a48e8
commit
867d923d18
@ -1,3 +1,22 @@
|
||||
Thu Oct 26 14:16:47 1995 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* xcofflink.c: Numerous changes to get closer to a working XCOFF
|
||||
linker.
|
||||
* libcoff-in.h (struct xcoff_tdata): Add full_aouthdr,
|
||||
toc_section, and entry_section fields.
|
||||
(struct xcoff_section_tdata): Remove ldrel_count field.
|
||||
* libcoff.h: Rebuild.
|
||||
* coffcode.h (coff_mkobject_hook): Initialize new xcoff_data
|
||||
fields.
|
||||
(coff_compute_section_file_positions): If RS6000COFF_C, generate
|
||||
full a.out header if full_aouthdr is set in xcoff_data.
|
||||
(coff_write_object_contents): Likewise. Set o_snentry and o_sntoc
|
||||
based on sections stored in xcoff_data.
|
||||
* coff-rs6000.c (xcoff_copy_private_bfd_data): Copy new xcoff_data
|
||||
fields.
|
||||
* coffgen.c (coff_get_symbol_info): If fix_value is set, fix the
|
||||
value stored in ret rather than returning a pointer value.
|
||||
|
||||
Wed Oct 25 23:10:39 1995 Michael Meissner <meissner@tiktok.cygnus.com>
|
||||
|
||||
* config.bfd (powerpc{,le}-{elf,sysv4,eabi,solaris2}): Remove MAC
|
||||
|
@ -102,7 +102,16 @@ xcoff_copy_private_bfd_data (ibfd, obfd)
|
||||
return true;
|
||||
ix = xcoff_data (ibfd);
|
||||
ox = xcoff_data (obfd);
|
||||
ox->full_aouthdr = ix->full_aouthdr;
|
||||
ox->toc = ix->toc;
|
||||
if (ix->toc_section == NULL)
|
||||
ox->toc_section = NULL;
|
||||
else
|
||||
ox->toc_section = ix->toc_section->output_section;
|
||||
if (ix->entry_section == NULL)
|
||||
ox->entry_section = NULL;
|
||||
else
|
||||
ox->entry_section = ix->entry_section->output_section;
|
||||
ox->text_align_power = ix->text_align_power;
|
||||
ox->data_align_power = ix->data_align_power;
|
||||
ox->modtype = ix->modtype;
|
||||
|
@ -1002,7 +1002,18 @@ coff_mkobject_hook (abfd, filehdr, aouthdr)
|
||||
struct xcoff_tdata *xcoff;
|
||||
|
||||
xcoff = xcoff_data (abfd);
|
||||
xcoff->full_aouthdr = true;
|
||||
xcoff->toc = internal_a->o_toc;
|
||||
if (internal_a->o_sntoc == 0)
|
||||
xcoff->toc_section = NULL;
|
||||
else
|
||||
xcoff->toc_section =
|
||||
coff_section_from_bfd_index (abfd, internal_a->o_sntoc);
|
||||
if (internal_a->o_snentry == 0)
|
||||
xcoff->entry_section = NULL;
|
||||
else
|
||||
xcoff->entry_section =
|
||||
coff_section_from_bfd_index (abfd, internal_a->o_snentry);
|
||||
xcoff->text_align_power = internal_a->o_algntext;
|
||||
xcoff->data_align_power = internal_a->o_algndata;
|
||||
xcoff->modtype = internal_a->o_modtype;
|
||||
@ -1764,6 +1775,8 @@ coff_compute_section_file_positions (abfd)
|
||||
if (abfd->flags & EXEC_P)
|
||||
sofar += AOUTSZ;
|
||||
#ifdef RS6000COFF_C
|
||||
else if (xcoff_data (abfd)->full_aouthdr)
|
||||
sofar += AOUTSZ;
|
||||
else
|
||||
sofar += SMALL_AOUTSZ;
|
||||
#endif
|
||||
@ -2003,7 +2016,10 @@ coff_write_object_contents (abfd)
|
||||
{
|
||||
scn_base = FILHSZ;
|
||||
#ifdef RS6000COFF_C
|
||||
scn_base += SMALL_AOUTSZ;
|
||||
if (xcoff_data (abfd)->full_aouthdr)
|
||||
scn_base += AOUTSZ;
|
||||
else
|
||||
scn_base += SMALL_AOUTSZ;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2135,8 +2151,10 @@ coff_write_object_contents (abfd)
|
||||
{
|
||||
internal_f.f_opthdr = 0;
|
||||
#ifdef RS6000COFF_C
|
||||
/* XCOFF seems to always write at least a small a.out header. */
|
||||
internal_f.f_opthdr = SMALL_AOUTSZ;
|
||||
if (xcoff_data (abfd)->full_aouthdr)
|
||||
internal_f.f_opthdr = AOUTSZ;
|
||||
else
|
||||
internal_f.f_opthdr = SMALL_AOUTSZ;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2311,22 +2329,20 @@ coff_write_object_contents (abfd)
|
||||
internal_f.f_nsyms = obj_raw_syment_count (abfd);
|
||||
|
||||
#ifdef RS6000COFF_C
|
||||
if ((abfd->flags & EXEC_P) != 0)
|
||||
if (xcoff_data (abfd)->full_aouthdr)
|
||||
{
|
||||
bfd_vma entry, toc;
|
||||
bfd_vma toc;
|
||||
asection *loader_sec;
|
||||
|
||||
entry = bfd_get_start_address (abfd);
|
||||
if (text_sec != NULL
|
||||
&& entry >= text_sec->vma
|
||||
&& entry < text_sec->vma + bfd_section_size (abfd, text_sec))
|
||||
internal_a.o_snentry = text_sec->target_index;
|
||||
else if (data_sec != NULL
|
||||
&& entry >= data_sec->vma
|
||||
&& entry < data_sec->vma + bfd_section_size (abfd, data_sec))
|
||||
internal_a.o_snentry = data_sec->target_index;
|
||||
if (xcoff_data (abfd)->entry_section != NULL)
|
||||
internal_a.o_snentry = xcoff_data (abfd)->entry_section->target_index;
|
||||
else
|
||||
internal_a.o_snentry = 0;
|
||||
{
|
||||
internal_a.o_snentry = 0;
|
||||
if (internal_a.entry == 0)
|
||||
internal_a.entry = (bfd_vma) -1;
|
||||
}
|
||||
|
||||
if (text_sec != NULL)
|
||||
{
|
||||
internal_a.o_sntext = text_sec->target_index;
|
||||
@ -2359,16 +2375,10 @@ coff_write_object_contents (abfd)
|
||||
|
||||
toc = xcoff_data (abfd)->toc;
|
||||
internal_a.o_toc = toc;
|
||||
if (text_sec != NULL
|
||||
&& toc >= text_sec->vma
|
||||
&& toc < text_sec->vma + bfd_section_size (abfd, text_sec))
|
||||
internal_a.o_sntoc = text_sec->target_index;
|
||||
else if (data_sec != NULL
|
||||
&& toc >= data_sec->vma
|
||||
&& toc < data_sec->vma + bfd_section_size (abfd, data_sec))
|
||||
internal_a.o_sntoc = data_sec->target_index;
|
||||
else
|
||||
if (xcoff_data (abfd)->toc_section == NULL)
|
||||
internal_a.o_sntoc = 0;
|
||||
else
|
||||
internal_a.o_sntoc = xcoff_data (abfd)->toc_section->target_index;
|
||||
|
||||
internal_a.o_modtype = xcoff_data (abfd)->modtype;
|
||||
if (xcoff_data (abfd)->cputype != -1)
|
||||
@ -2415,9 +2425,15 @@ coff_write_object_contents (abfd)
|
||||
else
|
||||
{
|
||||
AOUTHDR buff;
|
||||
size_t size;
|
||||
|
||||
/* XCOFF seems to always write at least a small a.out header. */
|
||||
coff_swap_aouthdr_out (abfd, (PTR) &internal_a, (PTR) &buff);
|
||||
if (bfd_write ((PTR) &buff, 1, SMALL_AOUTSZ, abfd) != SMALL_AOUTSZ)
|
||||
if (xcoff_data (abfd)->full_aouthdr)
|
||||
size = AOUTSZ;
|
||||
else
|
||||
size = SMALL_AOUTSZ;
|
||||
if (bfd_write ((PTR) &buff, 1, size, abfd) != size)
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
152
bfd/coffgen.c
152
bfd/coffgen.c
@ -329,6 +329,147 @@ coff_get_symtab (abfd, alocation)
|
||||
return bfd_get_symcount (abfd);
|
||||
}
|
||||
|
||||
/* Get the name of a symbol. The caller must pass in a buffer of size
|
||||
>= SYMNMLEN + 1. */
|
||||
|
||||
const char *
|
||||
_bfd_coff_internal_syment_name (abfd, sym, buf)
|
||||
bfd *abfd;
|
||||
const struct internal_syment *sym;
|
||||
char *buf;
|
||||
{
|
||||
/* FIXME: It's not clear this will work correctly if sizeof
|
||||
(_n_zeroes) != 4. */
|
||||
if (sym->_n._n_n._n_zeroes != 0
|
||||
|| sym->_n._n_n._n_offset == 0)
|
||||
{
|
||||
memcpy (buf, sym->_n._n_name, SYMNMLEN);
|
||||
buf[SYMNMLEN] = '\0';
|
||||
return buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *strings;
|
||||
|
||||
BFD_ASSERT (sym->_n._n_n._n_offset >= STRING_SIZE_SIZE);
|
||||
strings = obj_coff_strings (abfd);
|
||||
if (strings == NULL)
|
||||
{
|
||||
strings = _bfd_coff_read_string_table (abfd);
|
||||
if (strings == NULL)
|
||||
return NULL;
|
||||
}
|
||||
return strings + sym->_n._n_n._n_offset;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read in and swap the relocs. This returns a buffer holding the
|
||||
relocs for section SEC in file ABFD. If CACHE is true and
|
||||
INTERNAL_RELOCS is NULL, the relocs read in will be saved in case
|
||||
the function is called again. If EXTERNAL_RELOCS is not NULL, it
|
||||
is a buffer large enough to hold the unswapped relocs. If
|
||||
INTERNAL_RELOCS is not NULL, it is a buffer large enough to hold
|
||||
the swapped relocs. If REQUIRE_INTERNAL is true, then the return
|
||||
value must be INTERNAL_RELOCS. The function returns NULL on error. */
|
||||
|
||||
struct internal_reloc *
|
||||
_bfd_coff_read_internal_relocs (abfd, sec, cache, external_relocs,
|
||||
require_internal, internal_relocs)
|
||||
bfd *abfd;
|
||||
asection *sec;
|
||||
boolean cache;
|
||||
bfd_byte *external_relocs;
|
||||
boolean require_internal;
|
||||
struct internal_reloc *internal_relocs;
|
||||
{
|
||||
bfd_size_type relsz;
|
||||
bfd_byte *free_external = NULL;
|
||||
struct internal_reloc *free_internal = NULL;
|
||||
bfd_byte *erel;
|
||||
bfd_byte *erel_end;
|
||||
struct internal_reloc *irel;
|
||||
|
||||
if (coff_section_data (abfd, sec) != NULL
|
||||
&& coff_section_data (abfd, sec)->relocs != NULL)
|
||||
{
|
||||
if (! require_internal)
|
||||
return coff_section_data (abfd, sec)->relocs;
|
||||
memcpy (internal_relocs, coff_section_data (abfd, sec)->relocs,
|
||||
sec->reloc_count * sizeof (struct internal_reloc));
|
||||
return internal_relocs;
|
||||
}
|
||||
|
||||
relsz = bfd_coff_relsz (abfd);
|
||||
|
||||
if (external_relocs == NULL)
|
||||
{
|
||||
free_external = (bfd_byte *) malloc (sec->reloc_count * relsz);
|
||||
if (free_external == NULL && sec->reloc_count > 0)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
goto error_return;
|
||||
}
|
||||
external_relocs = free_external;
|
||||
}
|
||||
|
||||
if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
|
||||
|| (bfd_read (external_relocs, relsz, sec->reloc_count, abfd)
|
||||
!= relsz * sec->reloc_count))
|
||||
goto error_return;
|
||||
|
||||
if (internal_relocs == NULL)
|
||||
{
|
||||
free_internal = ((struct internal_reloc *)
|
||||
malloc (sec->reloc_count
|
||||
* sizeof (struct internal_reloc)));
|
||||
if (free_internal == NULL && sec->reloc_count > 0)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
goto error_return;
|
||||
}
|
||||
internal_relocs = free_internal;
|
||||
}
|
||||
|
||||
/* Swap in the relocs. */
|
||||
erel = external_relocs;
|
||||
erel_end = erel + relsz * sec->reloc_count;
|
||||
irel = internal_relocs;
|
||||
for (; erel < erel_end; erel += relsz, irel++)
|
||||
bfd_coff_swap_reloc_in (abfd, (PTR) erel, (PTR) irel);
|
||||
|
||||
if (free_external != NULL)
|
||||
{
|
||||
free (free_external);
|
||||
free_external = NULL;
|
||||
}
|
||||
|
||||
if (cache && free_internal != NULL)
|
||||
{
|
||||
if (coff_section_data (abfd, sec) == NULL)
|
||||
{
|
||||
sec->used_by_bfd =
|
||||
(PTR) bfd_zalloc (abfd,
|
||||
sizeof (struct coff_section_tdata));
|
||||
if (sec->used_by_bfd == NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
goto error_return;
|
||||
}
|
||||
coff_section_data (abfd, sec)->contents = NULL;
|
||||
}
|
||||
coff_section_data (abfd, sec)->relocs = free_internal;
|
||||
}
|
||||
|
||||
return internal_relocs;
|
||||
|
||||
error_return:
|
||||
if (free_external != NULL)
|
||||
free (free_external);
|
||||
if (free_internal != NULL)
|
||||
free (free_internal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set lineno_count for the output sections of a COFF file. */
|
||||
|
||||
int
|
||||
@ -1688,6 +1829,15 @@ coff_get_symbol_info (abfd, symbol, ret)
|
||||
symbol_info *ret;
|
||||
{
|
||||
bfd_symbol_info (symbol, ret);
|
||||
if (coffsymbol (symbol)->native != NULL
|
||||
&& coffsymbol (symbol)->native->fix_value)
|
||||
{
|
||||
combined_entry_type *psym;
|
||||
|
||||
psym = ((combined_entry_type *)
|
||||
coffsymbol (symbol)->native->u.syment.n_value);
|
||||
ret->value = (bfd_vma) (psym - obj_raw_syments (abfd));
|
||||
}
|
||||
}
|
||||
|
||||
/* Print out information about COFF symbol. */
|
||||
@ -1974,7 +2124,7 @@ coff_find_nearest_line (abfd, section, ignore_symbols, offset, filename_ptr,
|
||||
section->used_by_bfd =
|
||||
((PTR) bfd_zalloc (abfd,
|
||||
sizeof (struct coff_section_tdata)));
|
||||
sec_data = section->used_by_bfd;
|
||||
sec_data = (struct coff_section_tdata *) section->used_by_bfd;
|
||||
}
|
||||
if (sec_data != NULL)
|
||||
{
|
||||
|
@ -105,9 +105,18 @@ struct xcoff_tdata
|
||||
/* Basic COFF information. */
|
||||
coff_data_type coff;
|
||||
|
||||
/* True if a large a.out header should be generated. */
|
||||
boolean full_aouthdr;
|
||||
|
||||
/* TOC value. */
|
||||
bfd_vma toc;
|
||||
|
||||
/* Section holding TOC. */
|
||||
asection *toc_section;
|
||||
|
||||
/* Section holding entry point. */
|
||||
asection *entry_section;
|
||||
|
||||
/* .text alignment from optional header. */
|
||||
int text_align_power;
|
||||
|
||||
@ -178,8 +187,6 @@ struct xcoff_section_tdata
|
||||
by this csect. */
|
||||
unsigned long first_symndx;
|
||||
unsigned long last_symndx;
|
||||
/* The number of .loader relocs in this csect. */
|
||||
size_t ldrel_count;
|
||||
};
|
||||
|
||||
/* An accessor macro the xcoff_section_tdata structure. */
|
||||
|
@ -105,9 +105,18 @@ struct xcoff_tdata
|
||||
/* Basic COFF information. */
|
||||
coff_data_type coff;
|
||||
|
||||
/* True if a large a.out header should be generated. */
|
||||
boolean full_aouthdr;
|
||||
|
||||
/* TOC value. */
|
||||
bfd_vma toc;
|
||||
|
||||
/* Section holding TOC. */
|
||||
asection *toc_section;
|
||||
|
||||
/* Section holding entry point. */
|
||||
asection *entry_section;
|
||||
|
||||
/* .text alignment from optional header. */
|
||||
int text_align_power;
|
||||
|
||||
@ -178,8 +187,6 @@ struct xcoff_section_tdata
|
||||
by this csect. */
|
||||
unsigned long first_symndx;
|
||||
unsigned long last_symndx;
|
||||
/* The number of .loader relocs in this csect. */
|
||||
size_t ldrel_count;
|
||||
};
|
||||
|
||||
/* An accessor macro the xcoff_section_tdata structure. */
|
||||
|
381
bfd/xcofflink.c
381
bfd/xcofflink.c
@ -25,10 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#include "coff/internal.h"
|
||||
#include "libcoff.h"
|
||||
|
||||
/* This file holds the XCOFF linker code. A lot of it is very similar
|
||||
to the COFF linker code. However, it is different enough that I
|
||||
chose to avoid trying to hack up the COFF code to support XCOFF.
|
||||
That leads to a certain amount of duplicated code, alas. */
|
||||
/* This file holds the XCOFF linker code. */
|
||||
|
||||
#define STRING_SIZE_SIZE (4)
|
||||
|
||||
@ -1216,34 +1213,47 @@ xcoff_link_add_symbols (abfd, info)
|
||||
relbuf);
|
||||
if (relname == NULL)
|
||||
goto error_return;
|
||||
copy = (! info->keep_memory
|
||||
|| relsym._n._n_n._n_zeroes != 0
|
||||
|| relsym._n._n_n._n_offset == 0);
|
||||
h = xcoff_link_hash_lookup (xcoff_hash_table (info),
|
||||
relname, true, copy, false);
|
||||
if (h == NULL)
|
||||
goto error_return;
|
||||
|
||||
/* At this point h->root.type could be
|
||||
bfd_link_hash_new. That should be OK, since
|
||||
we know for sure that we will come across
|
||||
this symbol as we step through the file. */
|
||||
|
||||
/* We store h in *sym_hash for the convenience
|
||||
of the relocate_section function. */
|
||||
*sym_hash = h;
|
||||
|
||||
if (h->toc_section != NULL)
|
||||
/* We only merge TOC entries if the TC name is
|
||||
the same as the symbol name. This handles
|
||||
the normal case, but not common cases like
|
||||
SYM.P4 which gcc generates to store SYM + 4
|
||||
in the TOC. FIXME. */
|
||||
if (strcmp (name, relname) == 0)
|
||||
{
|
||||
/* We already have a TOC entry for this
|
||||
symbol, so we can just ignore this one. */
|
||||
*rel_csect = bfd_und_section_ptr;
|
||||
break;
|
||||
}
|
||||
copy = (! info->keep_memory
|
||||
|| relsym._n._n_n._n_zeroes != 0
|
||||
|| relsym._n._n_n._n_offset == 0);
|
||||
h = xcoff_link_hash_lookup (xcoff_hash_table (info),
|
||||
relname, true, copy,
|
||||
false);
|
||||
if (h == NULL)
|
||||
goto error_return;
|
||||
|
||||
/* We are about to create a TOC entry for this
|
||||
symbol. */
|
||||
set_toc = h;
|
||||
/* At this point h->root.type could be
|
||||
bfd_link_hash_new. That should be OK,
|
||||
since we know for sure that we will come
|
||||
across this symbol as we step through the
|
||||
file. */
|
||||
|
||||
/* We store h in *sym_hash for the
|
||||
convenience of the relocate_section
|
||||
function. */
|
||||
*sym_hash = h;
|
||||
|
||||
if (h->toc_section != NULL)
|
||||
{
|
||||
/* We already have a TOC entry for this
|
||||
symbol, so we can just ignore this
|
||||
one. */
|
||||
*rel_csect = bfd_und_section_ptr;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We are about to create a TOC entry for
|
||||
this symbol. */
|
||||
set_toc = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1431,7 +1441,7 @@ xcoff_link_add_symbols (abfd, info)
|
||||
csect = bfd_make_section_anyway (abfd, ".bss");
|
||||
if (csect == NULL)
|
||||
goto error_return;
|
||||
csect->vma = 0;
|
||||
csect->vma = sym.n_value;
|
||||
csect->_raw_size = aux.x_csect.x_scnlen.l;
|
||||
csect->flags |= SEC_ALLOC;
|
||||
csect->alignment_power = SMTYP_ALIGN (aux.x_csect.x_smtyp);
|
||||
@ -1524,6 +1534,21 @@ xcoff_link_add_symbols (abfd, info)
|
||||
(struct bfd_link_hash_entry **) sym_hash)))
|
||||
goto error_return;
|
||||
|
||||
if (smtyp == XTY_CM)
|
||||
{
|
||||
if ((*sym_hash)->root.type != bfd_link_hash_common
|
||||
|| (*sym_hash)->root.u.c.p->section != csect)
|
||||
{
|
||||
/* We don't need the common csect we just created. */
|
||||
csect->_raw_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*sym_hash)->root.u.c.p->alignment_power
|
||||
= csect->alignment_power;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->hash->creator == abfd->xvec)
|
||||
{
|
||||
int flag;
|
||||
@ -1574,75 +1599,49 @@ xcoff_link_add_symbols (abfd, info)
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/* We need to copy all relocs which are not PC relative
|
||||
and not TOC relative into the .loader section.
|
||||
|
||||
We also identify all symbols which are called, so
|
||||
that we can create glue code for calls to functions
|
||||
imported from dynamic objects. */
|
||||
|
||||
/* We identify all symbols which are called, so that we
|
||||
can create glue code for calls to functions imported
|
||||
from dynamic objects. */
|
||||
if (info->hash->creator == abfd->xvec
|
||||
&& *rel_csect != bfd_und_section_ptr)
|
||||
&& *rel_csect != bfd_und_section_ptr
|
||||
&& (rel->r_type == R_BR
|
||||
|| rel->r_type == R_RBR)
|
||||
&& obj_xcoff_sym_hashes (abfd)[rel->r_symndx] != NULL)
|
||||
{
|
||||
struct xcoff_link_hash_entry *h;
|
||||
|
||||
switch (rel->r_type)
|
||||
h = obj_xcoff_sym_hashes (abfd)[rel->r_symndx];
|
||||
h->flags |= XCOFF_CALLED;
|
||||
/* If the symbol name starts with a period, it is
|
||||
the code of a function. If the symbol is
|
||||
currently undefined, then add an undefined symbol
|
||||
for the function descriptor. This should do no
|
||||
harm, because any regular object that defines the
|
||||
function should also define the function
|
||||
descriptor. It helps, because it means that we
|
||||
will identify the function descriptor with a
|
||||
dynamic object if a dynamic object defines it. */
|
||||
if (h->root.root.string[0] == '.'
|
||||
&& h->descriptor == NULL)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case R_POS:
|
||||
case R_NEG:
|
||||
case R_RL:
|
||||
case R_RLA:
|
||||
++xcoff_hash_table (info)->ldrel_count;
|
||||
++xcoff_section_data (abfd, *rel_csect)->ldrel_count;
|
||||
h = obj_xcoff_sym_hashes (abfd)[rel->r_symndx];
|
||||
if (h != NULL)
|
||||
h->flags |= XCOFF_LDREL;
|
||||
break;
|
||||
case R_BR:
|
||||
case R_RBR:
|
||||
h = obj_xcoff_sym_hashes (abfd)[rel->r_symndx];
|
||||
if (h != NULL)
|
||||
{
|
||||
h->flags |= XCOFF_CALLED;
|
||||
/* If the symbol name starts with a period,
|
||||
it is the code of a function. If the
|
||||
symbol is currently undefined, then add
|
||||
an undefined symbol for the function
|
||||
descriptor. This should do no harm,
|
||||
because any regular object that defines
|
||||
the function should also define the
|
||||
function descriptor. It helps, because
|
||||
it means that we will identify the
|
||||
function descriptor with a dynamic object
|
||||
if a dynamic object defines it. */
|
||||
if (h->root.root.string[0] == '.'
|
||||
&& h->descriptor == NULL)
|
||||
{
|
||||
struct xcoff_link_hash_entry *hds;
|
||||
struct xcoff_link_hash_entry *hds;
|
||||
|
||||
hds = (xcoff_link_hash_lookup
|
||||
(xcoff_hash_table (info),
|
||||
h->root.root.string + 1, true, false,
|
||||
true));
|
||||
if (hds == NULL)
|
||||
goto error_return;
|
||||
if (hds->root.type == bfd_link_hash_new)
|
||||
{
|
||||
if (! (_bfd_generic_link_add_one_symbol
|
||||
(info, abfd, hds->root.root.string,
|
||||
(flagword) 0, bfd_und_section_ptr,
|
||||
(bfd_vma) 0, (const char *) NULL,
|
||||
false, false,
|
||||
((struct bfd_link_hash_entry **)
|
||||
NULL))))
|
||||
goto error_return;
|
||||
}
|
||||
h->descriptor = hds;
|
||||
}
|
||||
hds = xcoff_link_hash_lookup (xcoff_hash_table (info),
|
||||
h->root.root.string + 1,
|
||||
true, false, true);
|
||||
if (hds == NULL)
|
||||
goto error_return;
|
||||
if (hds->root.type == bfd_link_hash_new)
|
||||
{
|
||||
if (! (_bfd_generic_link_add_one_symbol
|
||||
(info, abfd, hds->root.root.string,
|
||||
(flagword) 0, bfd_und_section_ptr,
|
||||
(bfd_vma) 0, (const char *) NULL, false,
|
||||
false,
|
||||
(struct bfd_link_hash_entry **) NULL)))
|
||||
goto error_return;
|
||||
}
|
||||
break;
|
||||
h->descriptor = hds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1773,10 +1772,12 @@ xcoff_link_add_dynamic_symbols (abfd, info)
|
||||
|
||||
/* If the symbol is undefined, and the current BFD is
|
||||
not a dynamic object, change the BFD to this dynamic
|
||||
object, so that we can get the import file ID
|
||||
correctly. */
|
||||
if (h->root.u.undef.abfd == NULL
|
||||
|| (h->root.u.undef.abfd->flags & DYNAMIC) == 0)
|
||||
object, so that we can get the correct import file
|
||||
ID. */
|
||||
if ((h->root.type == bfd_link_hash_undefined
|
||||
|| h->root.type == bfd_link_hash_undefweak)
|
||||
&& (h->root.u.undef.abfd == NULL
|
||||
|| (h->root.u.undef.abfd->flags & DYNAMIC) == 0))
|
||||
h->root.u.undef.abfd = abfd;
|
||||
|
||||
if (h->smclas == XMC_UA
|
||||
@ -2024,7 +2025,13 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
|
||||
hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
|
||||
false, false, true);
|
||||
if (hentry != NULL)
|
||||
hentry->flags |= XCOFF_ENTRY;
|
||||
{
|
||||
hentry->flags |= XCOFF_ENTRY;
|
||||
if (hentry->root.type == bfd_link_hash_defined
|
||||
|| hentry->root.type == bfd_link_hash_defweak)
|
||||
xcoff_data (output_bfd)->entry_section =
|
||||
hentry->root.u.def.section->output_section;
|
||||
}
|
||||
|
||||
/* Garbage collect unused sections. */
|
||||
if (info->relocateable
|
||||
@ -2035,6 +2042,22 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
|
||||
{
|
||||
gc = false;
|
||||
xcoff_hash_table (info)->gc = false;
|
||||
|
||||
/* We still need to call xcoff_mark, in order to set ldrel_count
|
||||
correctly. */
|
||||
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
|
||||
{
|
||||
asection *o;
|
||||
|
||||
for (o = sub->sections; o != NULL; o = o->next)
|
||||
{
|
||||
if ((o->flags & SEC_MARK) == 0)
|
||||
{
|
||||
if (! xcoff_mark (info, o))
|
||||
goto error_return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2284,7 +2307,10 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
|
||||
}
|
||||
|
||||
/* The mark phase of garbage collection. For a given section, mark
|
||||
it, and all the sections which define symbols to which it refers. */
|
||||
it, and all the sections which define symbols to which it refers.
|
||||
Because this function needs to look at the relocs, we also count
|
||||
the number of relocs which need to be copied into the .loader
|
||||
section. */
|
||||
|
||||
static boolean
|
||||
xcoff_mark (info, sec)
|
||||
@ -2393,6 +2419,35 @@ xcoff_mark (info, sec)
|
||||
if (! xcoff_mark (info, rsec))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* See if this reloc needs to be copied into the .loader
|
||||
section. */
|
||||
switch (rel->r_type)
|
||||
{
|
||||
default:
|
||||
if (h == NULL
|
||||
|| h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak
|
||||
|| h->root.type == bfd_link_hash_common)
|
||||
break;
|
||||
/* Fall through. */
|
||||
case R_POS:
|
||||
case R_NEG:
|
||||
case R_RL:
|
||||
case R_RLA:
|
||||
++xcoff_hash_table (info)->ldrel_count;
|
||||
if (h != NULL)
|
||||
h->flags |= XCOFF_LDREL;
|
||||
break;
|
||||
case R_TOC:
|
||||
case R_GL:
|
||||
case R_TCL:
|
||||
case R_TRL:
|
||||
case R_TRLA:
|
||||
/* We should never need a .loader reloc for a TOC
|
||||
relative reloc. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! info->keep_memory
|
||||
@ -2441,10 +2496,6 @@ xcoff_sweep (info)
|
||||
o->_raw_size = 0;
|
||||
o->reloc_count = 0;
|
||||
o->lineno_count = 0;
|
||||
if (coff_section_data (sub, o) != NULL
|
||||
&& xcoff_section_data (sub, o) != NULL)
|
||||
xcoff_hash_table (info)->ldrel_count -=
|
||||
xcoff_section_data (sub, o)->ldrel_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2520,11 +2571,12 @@ xcoff_build_ldsyms (h, p)
|
||||
|
||||
/* We need to add a symbol to the .loader section if it is mentioned
|
||||
in a reloc which we are copying to the .loader section and it was
|
||||
not defined, or if it is the entry point. */
|
||||
not defined or common, or if it is the entry point. */
|
||||
|
||||
if (((h->flags & XCOFF_LDREL) == 0
|
||||
|| h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
|| h->root.type == bfd_link_hash_defweak
|
||||
|| h->root.type == bfd_link_hash_common)
|
||||
&& (h->flags & XCOFF_ENTRY) == 0)
|
||||
{
|
||||
h->ldsym = NULL;
|
||||
@ -2660,6 +2712,7 @@ _bfd_xcoff_bfd_final_link (abfd, info)
|
||||
+ xcoff_hash_table (info)->ldhdr.l_nsyms * LDSYMSZ));
|
||||
|
||||
xcoff_data (abfd)->coff.link_info = info;
|
||||
xcoff_data (abfd)->full_aouthdr = true;
|
||||
|
||||
finfo.strtab = _bfd_stringtab_init ();
|
||||
if (finfo.strtab == NULL)
|
||||
@ -2728,13 +2781,7 @@ _bfd_xcoff_bfd_final_link (abfd, info)
|
||||
code knows what compute_section_file_positions is going
|
||||
to do. */
|
||||
sofar = bfd_coff_filhsz (abfd);
|
||||
if ((abfd->flags & EXEC_P) != 0)
|
||||
sofar += bfd_coff_aoutsz (abfd);
|
||||
else
|
||||
{
|
||||
/* FIXME. */
|
||||
sofar += 28;
|
||||
}
|
||||
sofar += bfd_coff_aoutsz (abfd);
|
||||
sofar += abfd->section_count * bfd_coff_scnhsz (abfd);
|
||||
|
||||
for (o = abfd->sections; o != NULL; o = o->next)
|
||||
@ -3420,6 +3467,8 @@ xcoff_link_input_bfd (finfo, input_bfd)
|
||||
+ (*csectpp)->output_offset
|
||||
+ isym.n_value
|
||||
- (*csectpp)->vma);
|
||||
xcoff_data (finfo->output_bfd)->toc_section =
|
||||
(*csectpp)->output_section;
|
||||
require = true;
|
||||
}
|
||||
}
|
||||
@ -3441,7 +3490,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
|
||||
if (! skip
|
||||
&& isym.n_sclass == C_EXT
|
||||
&& smtyp == XTY_CM
|
||||
&& ((*sym_hash)->flags & XCOFF_DEF_REGULAR) != 0)
|
||||
&& (*sym_hash)->root.type != bfd_link_hash_common)
|
||||
skip = true;
|
||||
|
||||
/* Skip local symbols if we are discarding them. */
|
||||
@ -3531,26 +3580,9 @@ xcoff_link_input_bfd (finfo, input_bfd)
|
||||
}
|
||||
}
|
||||
|
||||
if (isym.n_sclass == C_BSTAT)
|
||||
{
|
||||
unsigned long indx;
|
||||
|
||||
/* The value of a C_BSTAT symbol is the symbol table
|
||||
index of the containing csect. */
|
||||
|
||||
indx = isym.n_value;
|
||||
if (indx < obj_raw_syment_count (input_bfd))
|
||||
{
|
||||
long symindx;
|
||||
|
||||
symindx = finfo->sym_indices[indx];
|
||||
if (symindx < 0)
|
||||
isym.n_value = 0;
|
||||
else
|
||||
isym.n_value = symindx;
|
||||
}
|
||||
}
|
||||
else if (isym.n_scnum > 0)
|
||||
if (isym.n_sclass != C_BSTAT
|
||||
&& isym.n_sclass != C_ESTAT
|
||||
&& isym.n_scnum > 0)
|
||||
{
|
||||
isym.n_scnum = (*csectpp)->output_section->target_index;
|
||||
isym.n_value += ((*csectpp)->output_section->vma
|
||||
@ -3635,9 +3667,10 @@ xcoff_link_input_bfd (finfo, input_bfd)
|
||||
*indexp++ = -1;
|
||||
}
|
||||
|
||||
/* Fix up the aux entries. This must be done in a separate pass,
|
||||
because we don't know the correct symbol indices until we have
|
||||
already decided which symbols we are going to keep. */
|
||||
/* Fix up the aux entries and the C_BSTAT symbols. This must be
|
||||
done in a separate pass, because we don't know the correct symbol
|
||||
indices until we have already decided which symbols we are going
|
||||
to keep. */
|
||||
|
||||
esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
|
||||
esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
|
||||
@ -3657,6 +3690,27 @@ xcoff_link_input_bfd (finfo, input_bfd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (isymp->n_sclass == C_BSTAT)
|
||||
{
|
||||
unsigned long indx;
|
||||
|
||||
/* The value of a C_BSTAT symbol is the symbol table
|
||||
index of the containing csect. */
|
||||
indx = isymp->n_value;
|
||||
if (indx < obj_raw_syment_count (input_bfd))
|
||||
{
|
||||
long symindx;
|
||||
|
||||
symindx = finfo->sym_indices[indx];
|
||||
if (symindx < 0)
|
||||
isymp->n_value = 0;
|
||||
else
|
||||
isymp->n_value = symindx;
|
||||
bfd_coff_swap_sym_out (output_bfd, (PTR) isymp,
|
||||
(PTR) outsym);
|
||||
}
|
||||
}
|
||||
|
||||
esym += isymesz;
|
||||
outsym += osymesz;
|
||||
|
||||
@ -4066,7 +4120,12 @@ xcoff_link_input_bfd (finfo, input_bfd)
|
||||
switch (irel->r_type)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
if (h == NULL
|
||||
|| h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak
|
||||
|| h->root.type == bfd_link_hash_common)
|
||||
break;
|
||||
/* Fall through. */
|
||||
case R_POS:
|
||||
case R_NEG:
|
||||
case R_RL:
|
||||
@ -4076,30 +4135,36 @@ xcoff_link_input_bfd (finfo, input_bfd)
|
||||
ldrel.l_vaddr = irel->r_vaddr;
|
||||
if (r_symndx == -1)
|
||||
ldrel.l_symndx = -1;
|
||||
else if (h == NULL)
|
||||
else if (h == NULL
|
||||
|| (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak
|
||||
|| h->root.type == bfd_link_hash_common))
|
||||
{
|
||||
asection *sec;
|
||||
|
||||
sec = xcoff_data (input_bfd)->csects[r_symndx];
|
||||
if ((sec->flags & SEC_CODE) != 0)
|
||||
ldrel.l_symndx = 0;
|
||||
else if ((sec->flags & SEC_HAS_CONTENTS) != 0)
|
||||
ldrel.l_symndx = 1;
|
||||
if (h == NULL)
|
||||
sec = xcoff_data (input_bfd)->csects[r_symndx];
|
||||
else if (h->root.type == bfd_link_hash_common)
|
||||
sec = h->root.u.c.p->section;
|
||||
else
|
||||
ldrel.l_symndx = 2;
|
||||
}
|
||||
else if (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
{
|
||||
asection *sec;
|
||||
sec = h->root.u.def.section;
|
||||
sec = sec->output_section;
|
||||
|
||||
sec = h->root.u.def.section->output_section;
|
||||
if ((sec->flags & SEC_CODE) != 0)
|
||||
if (strcmp (sec->name, ".text") == 0)
|
||||
ldrel.l_symndx = 0;
|
||||
else if ((sec->flags & SEC_HAS_CONTENTS) != 0)
|
||||
else if (strcmp (sec->name, ".data") == 0)
|
||||
ldrel.l_symndx = 1;
|
||||
else
|
||||
else if (strcmp (sec->name, ".bss") == 0)
|
||||
ldrel.l_symndx = 2;
|
||||
else
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
("%s: loader reloc in unrecognized section `%s'",
|
||||
bfd_get_filename (input_bfd),
|
||||
sec->name);
|
||||
bfd_set_error (bfd_error_nonrepresentable_section);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4117,7 +4182,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
|
||||
ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
|
||||
ldrel.l_rsecnm = o->output_section->target_index;
|
||||
if (xcoff_hash_table (finfo->info)->textro
|
||||
&& (o->output_section->flags & SEC_CODE) != 0)
|
||||
&& strcmp (o->output_section->name, ".text") == 0)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
("%s: loader reloc in read-only section %s",
|
||||
@ -4131,6 +4196,16 @@ xcoff_link_input_bfd (finfo, input_bfd)
|
||||
finfo->ldrel);
|
||||
BFD_ASSERT (sizeof (struct external_ldrel) == LDRELSZ);
|
||||
++finfo->ldrel;
|
||||
break;
|
||||
|
||||
case R_TOC:
|
||||
case R_GL:
|
||||
case R_TCL:
|
||||
case R_TRL:
|
||||
case R_TRLA:
|
||||
/* We should never need a .loader reloc for a TOC
|
||||
relative reloc. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user