/* POWER/PowerPC XCOFF linker support.
- Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
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.
+ This file is part of BFD, the Binary File Descriptor library.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "bfd.h"
#include "sysdep.h"
case bfd_archive:
/* If the archive has a map, do the usual search. We then need
- to check the archive for stripped dynamic objects, because
- they will not appear in the archive map even though they
- should, perhaps, be included. If the archive has no map, we
- just consider each object file in turn, since that apparently
- is what the AIX native linker does. */
+ to check the archive for dynamic objects, because they may not
+ appear in the archive map even though they should, perhaps, be
+ included. If the archive has no map, we just consider each object
+ file in turn, since that apparently is what the AIX native linker
+ does. */
if (bfd_has_map (abfd))
{
if (! (_bfd_generic_link_add_archive_symbols
{
bfd *member;
-
+
member = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
while (member != NULL)
{
if (bfd_check_format (member, bfd_object)
- && (! bfd_has_map (abfd)
- || ((member->flags & DYNAMIC) != 0
- && (member->flags & HAS_SYMS) == 0)))
+ && (info->hash->creator == member->xvec)
+ && (! bfd_has_map (abfd) || (member->flags & DYNAMIC) != 0))
{
boolean needed;
-
- if (! xcoff_link_check_archive_element (member, info, &needed))
+
+ if (! xcoff_link_check_archive_element (member, info,
+ &needed))
return false;
if (needed)
member->archive_pass = -1;
&& ! info->static_link)
{
if (! xcoff_link_add_dynamic_symbols (abfd, info))
- {
- return false;
- }
+ return false;
}
/* create the loader, toc, gl, ds and debug sections, if needed */
if (false == xcoff_link_create_extra_sections(abfd, info))
- {
- goto error_return;
- }
+ goto error_return;
if ((abfd->flags & DYNAMIC) != 0
&& ! info->static_link)
}
}
-
/* Don't let the linker relocation routines discard the symbols. */
obj_coff_keep_syms (abfd) = true;
bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
file_align, maxstack, maxdata, gc,
modtype, textro, export_defineds,
- special_sections)
+ special_sections, rtld)
bfd *output_bfd;
struct bfd_link_info *info;
const char *libpath;
boolean textro;
boolean export_defineds;
asection **special_sections;
+ boolean rtld;
{
struct xcoff_link_hash_entry *hentry;
asection *lsec;
if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
{
-
for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++)
special_sections[i] = NULL;
return true;
xcoff_hash_table (info)->file_align = file_align;
xcoff_hash_table (info)->textro = textro;
- if (entry == NULL)
- {
- hentry = NULL;
- }
- else
+ hentry = NULL;
+ if (entry != NULL)
{
hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
false, false, true);
}
/* __rtinit */
- if (info->init_function || info->fini_function) {
- struct xcoff_link_hash_entry *hrtinit;
- struct internal_ldsym *ldsym;
-
- hrtinit = xcoff_link_hash_lookup (xcoff_hash_table (info),
- "__rtinit",
- false, false, true);
- if (hrtinit != NULL)
- {
- xcoff_mark_symbol (info, hrtinit);
- hrtinit->flags |= (XCOFF_DEF_REGULAR | XCOFF_RTINIT);
- }
- else
- {
- (*_bfd_error_handler)
- (_("error: undefined symbol __rtinit"));
-
- return false;
- }
-
- /* __rtinit initalized here
- Some information, like the location of the .initfini seciton will
- be filled in later.
-
- name or offset taken care of below with bfd_xcoff_put_ldsymbol_name. */
- amt = sizeof (struct internal_ldsym);
- ldsym = (struct internal_ldsym *) bfd_malloc (amt);
-
- ldsym->l_value = 0; /* will be filled in later */
- ldsym->l_scnum = 2; /* data section */
- ldsym->l_smtype = XTY_SD; /* csect section definition */
- ldsym->l_smclas = 5; /* .rw */
- ldsym->l_ifile = 0; /* special system loader symbol */
- ldsym->l_parm = 0; /* NA */
-
- /* Force __rtinit to be the first symbol in the loader symbol table
- See xcoff_build_ldsyms
-
- The first 3 symbol table indices are reserved to indicate the data,
- text and bss sections. */
- BFD_ASSERT (0 == ldinfo.ldsym_count);
-
- hrtinit->ldindx = 3;
- ldinfo.ldsym_count = 1;
- hrtinit->ldsym = ldsym;
-
- if (false == bfd_xcoff_put_ldsymbol_name (ldinfo.output_bfd, &ldinfo,
- hrtinit->ldsym,
- hrtinit->root.root.string))
- {
+ if (info->init_function || info->fini_function || rtld == true)
+ {
+ struct xcoff_link_hash_entry *hsym;
+ struct internal_ldsym *ldsym;
+
+ hsym = xcoff_link_hash_lookup (xcoff_hash_table (info),
+ "__rtinit", false, false, true);
+ if (hsym == NULL)
+ {
+ (*_bfd_error_handler)
+ (_("error: undefined symbol __rtinit"));
+ return false;
+ }
+
+ xcoff_mark_symbol (info, hsym);
+ hsym->flags |= (XCOFF_DEF_REGULAR | XCOFF_RTINIT);
+
+ /* __rtinit initalized */
+ amt = sizeof (struct internal_ldsym);
+ ldsym = (struct internal_ldsym *) bfd_malloc (amt);
+
+ ldsym->l_value = 0; /* will be filled in later */
+ ldsym->l_scnum = 2; /* data section */
+ ldsym->l_smtype = XTY_SD; /* csect section definition */
+ ldsym->l_smclas = 5; /* .rw */
+ ldsym->l_ifile = 0; /* special system loader symbol */
+ ldsym->l_parm = 0; /* NA */
+
+ /* Force __rtinit to be the first symbol in the loader symbol table
+ See xcoff_build_ldsyms
+
+ The first 3 symbol table indices are reserved to indicate the data,
+ text and bss sections. */
+ BFD_ASSERT (0 == ldinfo.ldsym_count);
+
+ hsym->ldindx = 3;
+ ldinfo.ldsym_count = 1;
+ hsym->ldsym = ldsym;
+
+ if (false == bfd_xcoff_put_ldsymbol_name (ldinfo.output_bfd, &ldinfo,
+ hsym->ldsym,
+ hsym->root.root.string))
return false;
- }
-
- /* This symbol is written out by xcoff_write_global_symbol
- Set stuff up so xcoff_write_global_symbol logic works. */
- hrtinit->flags |= XCOFF_DEF_REGULAR | XCOFF_MARK;
- hrtinit->root.type = bfd_link_hash_defined;
- hrtinit->root.u.def.value = 0;
- }
+
+ /* This symbol is written out by xcoff_write_global_symbol
+ Set stuff up so xcoff_write_global_symbol logic works. */
+ hsym->flags |= XCOFF_DEF_REGULAR | XCOFF_MARK;
+ hsym->root.type = bfd_link_hash_defined;
+ hsym->root.u.def.value = 0;
+ }
/* Garbage collect unused sections. */
if (info->relocateable
csectpp = xcoff_data (sub)->csects;
- symesz = bfd_coff_symesz (sub);
- esym = (bfd_byte *) obj_coff_external_syms (sub);
- esymend = esym + symcount * symesz;
- while (esym < esymend)
+ /* Dynamic object do not have csectpp's. */
+ if (NULL != csectpp)
{
- struct internal_syment sym;
+ symesz = bfd_coff_symesz (sub);
+ esym = (bfd_byte *) obj_coff_external_syms (sub);
+ esymend = esym + symcount * symesz;
- bfd_coff_swap_sym_in (sub, (PTR) esym, (PTR) &sym);
+ while (esym < esymend)
+ {
+ struct internal_syment sym;
- *debug_index = (unsigned long) -1;
+ bfd_coff_swap_sym_in (sub, (PTR) esym, (PTR) &sym);
- if (sym._n._n_n._n_zeroes == 0
- && *csectpp != NULL
- && (! gc
- || ((*csectpp)->flags & SEC_MARK) != 0
- || *csectpp == bfd_abs_section_ptr)
- && bfd_coff_symname_in_debug (sub, &sym))
- {
- char *name;
- bfd_size_type indx;
+ *debug_index = (unsigned long) -1;
- name = (char *) debug_contents + sym._n._n_n._n_offset;
- indx = _bfd_stringtab_add (debug_strtab, name, true, true);
- if (indx == (bfd_size_type) -1)
- goto error_return;
- *debug_index = indx;
- }
+ if (sym._n._n_n._n_zeroes == 0
+ && *csectpp != NULL
+ && (! gc
+ || ((*csectpp)->flags & SEC_MARK) != 0
+ || *csectpp == bfd_abs_section_ptr)
+ && bfd_coff_symname_in_debug (sub, &sym))
+ {
+ char *name;
+ bfd_size_type indx;
- esym += (sym.n_numaux + 1) * symesz;
- csectpp += sym.n_numaux + 1;
- debug_index += sym.n_numaux + 1;
+ name = (char *) debug_contents + sym._n._n_n._n_offset;
+ indx = _bfd_stringtab_add (debug_strtab, name, true, true);
+ if (indx == (bfd_size_type) -1)
+ goto error_return;
+ *debug_index = indx;
+ }
+
+ esym += (sym.n_numaux + 1) * symesz;
+ csectpp += sym.n_numaux + 1;
+ debug_index += sym.n_numaux + 1;
+ }
}
free (debug_contents);
}
boolean
-bfd_xcoff_link_generate_rtinit (abfd, init, fini)
+bfd_xcoff_link_generate_rtinit (abfd, init, fini, rtld)
bfd *abfd;
const char *init;
const char *fini;
+ boolean rtld;
{
struct bfd_in_memory *bim;
abfd->direction = write_direction;
abfd->where = 0;
- if (false == bfd_xcoff_generate_rtinit (abfd, init, fini))
+ if (false == bfd_xcoff_generate_rtinit (abfd, init, fini, rtld))
return false;
/* need to reset to unknown or it will not be read back in correctly */
struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
bfd_size_type amt;
- /* __rtinit
- Special handling of this symbol to make is the first symbol in
- the loader symbol table. Make sure this pass through does not
- undo it. */
+ /* __rtinit, this symbol has special handling. */
if (h->flags & XCOFF_RTINIT)
- {
return true;
- }
/* If this is a final link, and the symbol was defined as a common
symbol in a regular object file, and there was no definition in
xcoff32 uses 4 bytes in the toc.
xcoff64 uses 8 bytes in the toc. */
if (bfd_xcoff_is_xcoff64 (ldinfo->output_bfd))
- {
- byte_size = 8;
- }
+ byte_size = 8;
else if (bfd_xcoff_is_xcoff32 (ldinfo->output_bfd))
- {
- byte_size = 4;
- }
+ byte_size = 4;
else
- {
- return false;
- }
+ return false;
hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
hds->u.toc_offset = hds->toc_section->_raw_size;
{
boolean saw_contents;
int indx;
- asection **op, **prev;
+ asection **op;
file_ptr sofar;
/* Insert .pad sections before every section which has
contents and is loaded, if it is preceded by some other
section which has contents and is loaded. */
saw_contents = true;
- for (op = &abfd->sections, prev = NULL;
- *op != NULL; prev = op, op = &(*op)->next)
+ for (op = &abfd->sections; *op != NULL; op = &(*op)->next)
{
if (strcmp ((*op)->name, ".pad") == 0)
saw_contents = false;
saw_contents = true;
else
{
- asection *n, *hold, **st;
+ asection *n, **st;
/* Create a pad section and place it before the section
that needs padding. This requires unlinking and
- relinking the bfd's sections list.
-
- sections = S1
- . S1.next = S2
- . S2.next = S3
- . S3.next = NULL
- section_tail = &S3.next */
+ relinking the bfd's section list. */
- hold = *op;
st = abfd->section_tail;
-
n = bfd_make_section_anyway (abfd, ".pad");
n->flags = SEC_HAS_CONTENTS;
n->alignment_power = 0;
-
- if (NULL == prev)
- abfd->sections = n;
- else
- (*prev)->next = n;
-
- n->next = hold;
- *st = NULL;
- abfd->section_tail = st;
+ BFD_ASSERT (*st == n);
+ bfd_section_list_remove (abfd, st);
+ bfd_section_list_insert (abfd, op, n);
+
+ op = &n->next;
saw_contents = false;
}
}