aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1995-10-26 18:25:13 +0000
committerIan Lance Taylor <ian@airs.com>1995-10-26 18:25:13 +0000
commit867d923d18ef7eed7d016fdc04e8cf494d3c5db4 (patch)
tree5a28d483a9744201ad00936f826b774ff6a82bed /bfd
parent328e5a48e87d75e0d0b63669c533025da6242a5e (diff)
downloadfsf-binutils-gdb-867d923d18ef7eed7d016fdc04e8cf494d3c5db4.zip
fsf-binutils-gdb-867d923d18ef7eed7d016fdc04e8cf494d3c5db4.tar.gz
fsf-binutils-gdb-867d923d18ef7eed7d016fdc04e8cf494d3c5db4.tar.bz2
* 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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog19
-rw-r--r--bfd/coff-rs6000.c9
-rw-r--r--bfd/coffcode.h66
-rw-r--r--bfd/coffgen.c152
-rw-r--r--bfd/libcoff-in.h11
-rw-r--r--bfd/libcoff.h11
-rw-r--r--bfd/xcofflink.c381
7 files changed, 466 insertions, 183 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index f3cfd6d..963176a 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index 10d5450..f837a08 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -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;
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index e3eeb13..ff1406a 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -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
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index a65776d..9ccd2b7 100644
--- a/bfd/coffgen.c
+++ b/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)
{
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 0dd0184..7b818aa 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -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. */
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index ebdcdfb..f75c42b 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -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. */
diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index 6039620..0e272f5 100644
--- a/bfd/xcofflink.c
+++ b/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;
+
+ /* 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;
+ /* 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)
+ 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)
{
- 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;
-
- 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;
- }
+ 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;
}
}