/* POWER/PowerPC XCOFF linker support.
- Copyright 1995 Free Software Foundation, Inc.
+ Copyright 1995, 1996 Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
ret = ((struct xcoff_link_hash_entry *)
bfd_hash_allocate (table, sizeof (struct xcoff_link_hash_entry)));
if (ret == (struct xcoff_link_hash_entry *) NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return (struct bfd_hash_entry *) ret;
- }
+ return (struct bfd_hash_entry *) ret;
/* Call the allocation method of the superclass. */
ret = ((struct xcoff_link_hash_entry *)
ret = ((struct xcoff_link_hash_table *)
bfd_alloc (abfd, sizeof (struct xcoff_link_hash_table)));
if (ret == (struct xcoff_link_hash_table *) NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return (struct bfd_link_hash_table *) NULL;
- }
+ return (struct bfd_link_hash_table *) NULL;
if (! _bfd_link_hash_table_init (&ret->root, abfd, xcoff_link_hash_newfunc))
{
bfd_release (abfd, ret);
if ((abfd->flags & DYNAMIC) != 0
&& ! info->static_link)
- return xcoff_link_add_dynamic_symbols (abfd, info);
-
- n_tmask = coff_data (abfd)->local_n_tmask;
- n_btshft = coff_data (abfd)->local_n_btshft;
-
- /* Define macros so that ISFCN, et. al., macros work correctly. */
-#define N_TMASK n_tmask
-#define N_BTSHFT n_btshft
+ {
+ if (! xcoff_link_add_dynamic_symbols (abfd, info))
+ return false;
+ }
/* We need to build a .loader section, so we do it here. This won't
- work if we're producing an XCOFF output file with no non dynamic
- XCOFF input files. FIXME. */
+ work if we're producing an XCOFF output file with no XCOFF input
+ files. FIXME. */
if (xcoff_hash_table (info)->loader_section == NULL)
{
asection *lsec;
dsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
}
+ if ((abfd->flags & DYNAMIC) != 0
+ && ! info->static_link)
+ return true;
+
+ n_tmask = coff_data (abfd)->local_n_tmask;
+ n_btshft = coff_data (abfd)->local_n_btshft;
+
+ /* Define macros so that ISFCN, et. al., macros work correctly. */
+#define N_TMASK n_tmask
+#define N_BTSHFT n_btshft
+
if (info->keep_memory)
default_copy = false;
else
(symcount
* sizeof (struct xcoff_link_hash_entry *))));
if (sym_hash == NULL && symcount != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
coff_data (abfd)->sym_hashes = (struct coff_link_hash_entry **) sym_hash;
memset (sym_hash, 0,
(size_t) symcount * sizeof (struct xcoff_link_hash_entry *));
csect_cache = ((asection **)
bfd_alloc (abfd, symcount * sizeof (asection *)));
if (csect_cache == NULL && symcount != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
xcoff_data (abfd)->csects = csect_cache;
memset (csect_cache, 0, (size_t) symcount * sizeof (asection *));
scanning along the relocs as we process the csects. We index
into reloc_info using the section target_index. */
reloc_info = ((struct reloc_info_struct *)
- malloc ((abfd->section_count + 1)
- * sizeof (struct reloc_info_struct)));
+ bfd_malloc ((abfd->section_count + 1)
+ * sizeof (struct reloc_info_struct)));
if (reloc_info == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
memset ((PTR) reloc_info, 0,
(abfd->section_count + 1) * sizeof (struct reloc_info_struct));
xcoff_read_internal_relocs (abfd, o, true, (bfd_byte *) NULL,
false, (struct internal_reloc *) NULL);
reloc_info[o->target_index].csects =
- (asection **) malloc (o->reloc_count * sizeof (asection *));
+ (asection **) bfd_malloc (o->reloc_count * sizeof (asection *));
if (reloc_info[o->target_index].csects == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
memset (reloc_info[o->target_index].csects, 0,
o->reloc_count * sizeof (asection *));
}
{
bfd_byte *linenos;
- linenos = (bfd_byte *) malloc (o->lineno_count * linesz);
+ linenos = (bfd_byte *) bfd_malloc (o->lineno_count * linesz);
if (linenos == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
reloc_info[o->target_index].linenos = linenos;
if (bfd_seek (abfd, o->line_filepos, SEEK_SET) != 0
|| (bfd_read (linenos, linesz, o->lineno_count, abfd)
((struct coff_section_tdata *)
bfd_zalloc (abfd, sizeof (struct coff_section_tdata)));
if (csect->used_by_bfd == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
coff_section_data (abfd, csect)->tdata =
bfd_zalloc (abfd, sizeof (struct xcoff_section_tdata));
if (coff_section_data (abfd, csect)->tdata == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
xcoff_section_data (abfd, csect)->enclosing = enclosing;
xcoff_section_data (abfd, csect)->lineno_count =
enclosing->lineno_count;
((struct coff_section_tdata *)
bfd_zalloc (abfd, sizeof (struct coff_section_tdata)));
if (csect->used_by_bfd == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
coff_section_data (abfd, csect)->tdata =
bfd_zalloc (abfd, sizeof (struct xcoff_section_tdata));
if (coff_section_data (abfd, csect)->tdata == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
xcoff_section_data (abfd, csect)->first_symndx = csect_index;
if (first_csect == NULL)
goto error_return;
}
- buf = (bfd_byte *) malloc (lsec->_raw_size);
+ buf = (bfd_byte *) bfd_malloc (lsec->_raw_size);
if (buf == NULL && lsec->_raw_size > 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
if (! bfd_get_section_contents (abfd, lsec, (PTR) buf, (file_ptr) 0,
lsec->_raw_size))
n = ((struct xcoff_import_file *)
bfd_alloc (abfd, sizeof (struct xcoff_import_file)));
if (n == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
n->next = NULL;
/* For some reason, the path entry in the import file list for a
n = ((struct xcoff_link_size_list *)
bfd_alloc (output_bfd, sizeof (struct xcoff_link_size_list)));
if (n == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
n->next = xcoff_hash_table (info)->size_list;
n->h = h;
n->size = size;
h->ldsym = ((struct internal_ldsym *)
bfd_zalloc (output_bfd, sizeof (struct internal_ldsym)));
if (h->ldsym == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
}
if (imppath == NULL)
n = ((struct xcoff_import_file *)
bfd_alloc (output_bfd, sizeof (struct xcoff_import_file)));
if (n == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
n->next = NULL;
n->path = imppath;
n->file = impfile;
char *fnname;
struct xcoff_link_hash_entry *hfn;
- fnname = (char *) malloc (strlen (h->root.root.string + 2));
+ fnname = (char *) bfd_malloc (strlen (h->root.root.string) + 2);
if (fnname == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
fnname[0] = '.';
strcpy (fnname + 1, h->root.root.string);
hfn = xcoff_link_hash_lookup (xcoff_hash_table (info),
bfd *output_bfd;
/* Link information structure. */
struct bfd_link_info *info;
+ /* Whether all defined symbols should be exported. */
+ boolean export_defineds;
/* Number of ldsym structures. */
size_t ldsym_count;
/* Size of string table. */
.loader section before the linker lays out the output file.
LIBPATH is the library path to search for shared objects; this is
normally built from the -L arguments passed to the linker. ENTRY
- is the name of the entry point symbol. */
+ is the name of the entry point symbol (the -e linker option).
+ FILE_ALIGN is the alignment to use for sections within the file
+ (the -H linker option). MAXSTACK is the maximum stack size (the
+ -bmaxstack linker option). MAXDATA is the maximum data size (the
+ -bmaxdata linker option). GC is whether to do garbage collection
+ (the -bgc linker option). MODTYPE is the module type (the
+ -bmodtype linker option). TEXTRO is whether the text section must
+ be read only (the -btextro linker option). EXPORT_DEFINEDS is
+ whether all defined symbols should be exported (the -unix linker
+ option). SPECIAL_SECTIONS is set by this routine to csects with
+ magic names like _end. */
boolean
bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
file_align, maxstack, maxdata, gc,
- modtype, textro, special_sections)
+ modtype, textro, export_defineds,
+ special_sections)
bfd *output_bfd;
struct bfd_link_info *info;
const char *libpath;
boolean gc;
int modtype;
boolean textro;
+ boolean export_defineds;
asection **special_sections;
{
struct xcoff_link_hash_entry *hentry;
bfd_byte *debug_contents = NULL;
if (! XCOFF_XVECP (output_bfd->xvec))
- return true;
+ {
+ for (i = 0; i < 6; i++)
+ special_sections[i] = NULL;
+ return true;
+ }
ldinfo.failed = false;
ldinfo.output_bfd = output_bfd;
ldinfo.info = info;
+ ldinfo.export_defineds = export_defineds;
ldinfo.ldsym_count = 0;
ldinfo.string_size = 0;
ldinfo.strings = NULL;
lsec->_raw_size = stoff + ldhdr->l_stlen;
lsec->contents = (bfd_byte *) bfd_zalloc (output_bfd, lsec->_raw_size);
if (lsec->contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
/* Set up the header. */
xcoff_swap_ldhdr_out (output_bfd, ldhdr,
{
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;
- }
+ goto error_return;
}
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;
- }
+ 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);
if (sec->contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
}
/* Now that we've done garbage collection, figure out the contents
debug_index = ((unsigned long *)
bfd_zalloc (sub, symcount * sizeof (unsigned long)));
if (debug_index == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
xcoff_data (sub)->debug_indices = debug_index;
/* Grab the contents of the .debug section. We use malloc and
bfd_alloc, because I expect that, when linking many files
together, many of the strings will be the same. Storing the
strings in the hash table should save space in this case. */
- debug_contents = (bfd_byte *) malloc (subdeb->_raw_size);
+ debug_contents = (bfd_byte *) bfd_malloc (subdeb->_raw_size);
if (debug_contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
if (! bfd_get_section_contents (sub, subdeb, (PTR) debug_contents,
(file_ptr) 0, subdeb->_raw_size))
goto error_return;
struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
size_t len;
+ /* If all defined symbols should be exported, mark them now. */
+ if (ldinfo->export_defineds
+ && (h->flags & XCOFF_DEF_REGULAR) != 0)
+ h->flags |= XCOFF_EXPORT;
+
/* We don't want to garbage collect symbols which are not defined in
XCOFF files. This is a convenient place to mark them. */
if (xcoff_hash_table (ldinfo->info)->gc
if (h->ldsym == NULL)
{
ldinfo->failed = true;
- bfd_set_error (bfd_error_no_memory);
return false;
}
}
while (ldinfo->string_size + len + 3 > newalc)
newalc *= 2;
- if (ldinfo->strings == NULL)
- newstrings = (bfd_byte *) malloc (newalc);
- else
- newstrings = ((bfd_byte *)
- realloc ((PTR) ldinfo->strings, newalc));
+ newstrings = ((bfd_byte *)
+ bfd_realloc ((PTR) ldinfo->strings, newalc));
if (newstrings == NULL)
{
ldinfo->failed = true;
- bfd_set_error (bfd_error_no_memory);
return false;
}
ldinfo->string_alc = newalc;
if (finfo.strtab == NULL)
goto error_return;
+ /* Count the line number and relocation entries required for the
+ output file. Determine a few maximum sizes. */
+ max_contents_size = 0;
+ max_lineno_count = 0;
+ max_reloc_count = 0;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ o->reloc_count = 0;
+ o->lineno_count = 0;
+ for (p = o->link_order_head; p != NULL; p = p->next)
+ {
+ if (p->type == bfd_indirect_link_order)
+ {
+ asection *sec;
+
+ sec = p->u.indirect.section;
+
+ if (info->strip == strip_none
+ || info->strip == strip_some)
+ o->lineno_count += sec->lineno_count;
+
+ o->reloc_count += sec->reloc_count;
+
+ if (sec->_raw_size > max_contents_size)
+ max_contents_size = sec->_raw_size;
+ if (sec->lineno_count > max_lineno_count)
+ max_lineno_count = sec->lineno_count;
+ if (coff_section_data (sec->owner, sec) != NULL
+ && xcoff_section_data (sec->owner, sec) != NULL
+ && (xcoff_section_data (sec->owner, sec)->lineno_count
+ > max_lineno_count))
+ max_lineno_count =
+ xcoff_section_data (sec->owner, sec)->lineno_count;
+ if (sec->reloc_count > max_reloc_count)
+ max_reloc_count = sec->reloc_count;
+ }
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ ++o->reloc_count;
+ }
+ }
+
/* Compute the file positions for all the sections. */
if (abfd->output_has_begun)
{
sofar = bfd_coff_filhsz (abfd);
sofar += bfd_coff_aoutsz (abfd);
sofar += abfd->section_count * bfd_coff_scnhsz (abfd);
+ for (o = abfd->sections; o != NULL; o = o->next)
+ if (o->reloc_count >= 0xffff || o->lineno_count >= 0xffff)
+ sofar += bfd_coff_scnhsz (abfd);
for (o = abfd->sections; o != NULL; o = o->next)
{
bfd_coff_compute_section_file_positions (abfd);
}
- /* Count the line numbers and relocation entries required for the
- output file. Set the file positions for the relocs. */
- rel_filepos = obj_relocbase (abfd);
- relsz = bfd_coff_relsz (abfd);
- max_contents_size = 0;
- max_lineno_count = 0;
- max_reloc_count = 0;
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- o->reloc_count = 0;
- o->lineno_count = 0;
- for (p = o->link_order_head; p != NULL; p = p->next)
- {
- if (p->type == bfd_indirect_link_order)
- {
- asection *sec;
-
- sec = p->u.indirect.section;
-
- if (info->strip == strip_none
- || info->strip == strip_some)
- o->lineno_count += sec->lineno_count;
-
- o->reloc_count += sec->reloc_count;
-
- if (sec->_raw_size > max_contents_size)
- max_contents_size = sec->_raw_size;
- if (sec->lineno_count > max_lineno_count)
- max_lineno_count = sec->lineno_count;
- if (coff_section_data (sec->owner, sec) != NULL
- && xcoff_section_data (sec->owner, sec) != NULL
- && (xcoff_section_data (sec->owner, sec)->lineno_count
- > max_lineno_count))
- max_lineno_count =
- xcoff_section_data (sec->owner, sec)->lineno_count;
- if (sec->reloc_count > max_reloc_count)
- max_reloc_count = sec->reloc_count;
- }
- else if (p->type == bfd_section_reloc_link_order
- || p->type == bfd_symbol_reloc_link_order)
- ++o->reloc_count;
- }
- if (o->reloc_count == 0)
- o->rel_filepos = 0;
- else
- {
- o->flags |= SEC_RELOC;
- o->rel_filepos = rel_filepos;
- rel_filepos += o->reloc_count * relsz;
- }
- }
-
/* Allocate space for the pointers we need to keep for the relocs. */
{
unsigned int i;
/* We use section_count + 1, rather than section_count, because
the target_index fields are 1 based. */
- finfo.section_info = ((struct xcoff_link_section_info *)
- malloc ((abfd->section_count + 1)
- * sizeof (struct xcoff_link_section_info)));
+ finfo.section_info =
+ ((struct xcoff_link_section_info *)
+ bfd_malloc ((abfd->section_count + 1)
+ * sizeof (struct xcoff_link_section_info)));
if (finfo.section_info == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
for (i = 0; i <= abfd->section_count; i++)
{
finfo.section_info[i].relocs = NULL;
}
}
- /* We now know the size of the relocs, so we can determine the file
- positions of the line numbers. */
- line_filepos = rel_filepos;
- finfo.line_filepos = line_filepos;
- linesz = bfd_coff_linesz (abfd);
+ /* Set the file positions for the relocs. */
+ rel_filepos = obj_relocbase (abfd);
+ relsz = bfd_coff_relsz (abfd);
max_output_reloc_count = 0;
for (o = abfd->sections; o != NULL; o = o->next)
{
- if (o->lineno_count == 0)
- o->line_filepos = 0;
+ if (o->reloc_count == 0)
+ o->rel_filepos = 0;
else
{
- o->line_filepos = line_filepos;
- line_filepos += o->lineno_count * linesz;
- }
+ o->flags |= SEC_RELOC;
+ o->rel_filepos = rel_filepos;
+ rel_filepos += o->reloc_count * relsz;
- if (o->reloc_count != 0)
- {
/* We don't know the indices of global symbols until we have
written out all the local symbols. For each section in
the output file, we keep an array of pointers to hash
would be slow. */
finfo.section_info[o->target_index].relocs =
((struct internal_reloc *)
- malloc (o->reloc_count * sizeof (struct internal_reloc)));
+ bfd_malloc (o->reloc_count * sizeof (struct internal_reloc)));
finfo.section_info[o->target_index].rel_hashes =
((struct xcoff_link_hash_entry **)
- malloc (o->reloc_count
+ bfd_malloc (o->reloc_count
* sizeof (struct xcoff_link_hash_entry *)));
if (finfo.section_info[o->target_index].relocs == NULL
|| finfo.section_info[o->target_index].rel_hashes == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
if (o->reloc_count > max_output_reloc_count)
max_output_reloc_count = o->reloc_count;
}
+ }
+
+ /* We now know the size of the relocs, so we can determine the file
+ positions of the line numbers. */
+ line_filepos = rel_filepos;
+ finfo.line_filepos = line_filepos;
+ linesz = bfd_coff_linesz (abfd);
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if (o->lineno_count == 0)
+ o->line_filepos = 0;
+ else
+ {
+ o->line_filepos = line_filepos;
+ line_filepos += o->lineno_count * linesz;
+ }
/* Reset the reloc and lineno counts, so that we can use them to
count the number of entries we have output so far. */
/* Allocate some buffers used while linking. */
finfo.internal_syms = ((struct internal_syment *)
- malloc (max_sym_count
- * sizeof (struct internal_syment)));
- finfo.sym_indices = (long *) malloc (max_sym_count * sizeof (long));
+ bfd_malloc (max_sym_count
+ * sizeof (struct internal_syment)));
+ finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
finfo.outsyms = ((bfd_byte *)
- malloc ((size_t) ((max_sym_count + 1) * symesz)));
- finfo.linenos = (bfd_byte *) malloc (max_lineno_count
- * bfd_coff_linesz (abfd));
- finfo.contents = (bfd_byte *) malloc (max_contents_size);
- finfo.external_relocs = (bfd_byte *) malloc (max_reloc_count * relsz);
+ bfd_malloc ((size_t) ((max_sym_count + 1) * symesz)));
+ finfo.linenos = (bfd_byte *) bfd_malloc (max_lineno_count
+ * bfd_coff_linesz (abfd));
+ finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
+ finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz);
if ((finfo.internal_syms == NULL && max_sym_count > 0)
|| (finfo.sym_indices == NULL && max_sym_count > 0)
|| finfo.outsyms == NULL
|| (finfo.linenos == NULL && max_lineno_count > 0)
|| (finfo.contents == NULL && max_contents_size > 0)
|| (finfo.external_relocs == NULL && max_reloc_count > 0))
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
+ goto error_return;
obj_raw_syment_count (abfd) = 0;
xcoff_data (abfd)->toc = (bfd_vma) -1;
skip = true;
else
{
+ bfd_vma tocval, tocend;
+
+ tocval = ((*csectpp)->output_section->vma
+ + (*csectpp)->output_offset
+ + isym.n_value
+ - (*csectpp)->vma);
+ /* We want to find out if tocval is a good value to use
+ as the TOC anchor--that is, whether we can access all
+ of the TOC using a 16 bit offset from tocval. This
+ test assumes that the TOC comes at the end of the
+ output section, as it does in the default linker
+ script. If the TOC anchor is too far into the .toc
+ section, the relocation routine will report
+ overflows. */
+ tocend = ((*csectpp)->output_section->vma
+ + (*csectpp)->output_section->_raw_size);
+ if (tocval + 0x8000 < tocend)
+ {
+ bfd_vma tocadd;
+
+ tocadd = tocend - (tocval + 0x8000);
+ tocval += tocadd;
+ isym.n_value += tocadd;
+ }
+
finfo->toc_symindx = output_index;
- xcoff_data (finfo->output_bfd)->toc =
- ((*csectpp)->output_section->vma
- + (*csectpp)->output_offset
- + isym.n_value
- - (*csectpp)->vma);
+ xcoff_data (finfo->output_bfd)->toc = tocval;
xcoff_data (finfo->output_bfd)->toc_section =
(*csectpp)->output_section;
require = true;
bfd_alloc (finfo->output_bfd,
sizeof (struct xcoff_toc_rel_hash)));
if (n == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
si = finfo->section_info + target_index;
n->next = si->toc_rel_hashes;
n->h = h;
- xcoff_data (output_bfd)->toc);
if ((h->descriptor->flags & XCOFF_SET_TOC) != 0)
tocoff += h->descriptor->u.toc_offset;
- bfd_put_32 (output_bfd, XCOFF_GLINK_FIRST | tocoff, p);
+ bfd_put_32 (output_bfd, XCOFF_GLINK_FIRST | (tocoff & 0xffff), p);
for (i = 0, p += 4;
i < sizeof xcoff_glink_code / sizeof xcoff_glink_code[0];
i++, p += 4)
size = bfd_get_reloc_size (howto);
buf = (bfd_byte *) bfd_zmalloc (size);
if (buf == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ return false;
rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
switch (rstat)
else
{
sec = sections[symndx];
- val = (sec->output_section->vma
- + sec->output_offset
- + sym->n_value
- - sec->vma);
+ /* Hack to make sure we use the right TOC anchor value
+ if this reloc is against the TOC anchor. */
+ if (sec->name[3] == '0'
+ && strcmp (sec->name, ".tc0") == 0)
+ val = xcoff_data (output_bfd)->toc;
+ else
+ val = (sec->output_section->vma
+ + sec->output_offset
+ + sym->n_value
+ - sec->vma);
}
}
else