aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog30
-rw-r--r--bfd/coff-rs6000.c25
-rw-r--r--bfd/coff64-rs6000.c25
-rw-r--r--bfd/xcofflink.c446
-rw-r--r--include/coff/ChangeLog6
-rw-r--r--include/coff/xcoff.h10
-rw-r--r--ld/ChangeLog7
-rw-r--r--ld/emultempl/aix.em6
-rw-r--r--ld/testsuite/ChangeLog7
-rw-r--r--ld/testsuite/ld-powerpc/aix-glink-1-32.d5
-rw-r--r--ld/testsuite/ld-powerpc/aix-glink-1-32.dd44
-rw-r--r--ld/testsuite/ld-powerpc/aix-glink-1-64.d5
-rw-r--r--ld/testsuite/ld-powerpc/aix-glink-1-64.dd49
-rw-r--r--ld/testsuite/ld-powerpc/aix-glink-1.ex2
-rw-r--r--ld/testsuite/ld-powerpc/aix-glink-1.s21
-rw-r--r--ld/testsuite/ld-powerpc/aix52.exp6
16 files changed, 463 insertions, 231 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 818054c..477d2f7 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,35 @@
2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com>
+ * coff-rs6000.c (xcoff_ppc_relocate_section): Report relocations
+ against undefined symbols if the symbol's XCOFF_WAS_UNDEFINED
+ flag is set. Assert that all undefined symbols are either
+ imported or defined by a dynamic object.
+ * coff64-rs6000.c (xcoff64_ppc_relocate_section): Likewise.
+ * xcofflink.c (xcoff_link_add_symbols): Extend function-symbol
+ handling to all relocations. Only set XCOFF_CALLED for function
+ symbols.
+ (xcoff_find_function): New function, split out from...
+ (bfd_xcoff_export_symbol) ...here.
+ (xcoff_set_import_path): New function, split out from...
+ (bfd_xcoff_import_symbol): ...here. Remove assertion for old
+ meaning of XCOFF_CALLED.
+ (xcoff_mark_symbol): If we mark an undefined and unimported
+ symbol, find some way of defining it. If the symbol is a function
+ descriptor, fill in its definition automatically. If the symbol
+ is a function, mark its descriptor and allocate room for global
+ linkage code. Otherwise mark the symbol as implicitly imported.
+ Move the code for creating function descriptors from...
+ (xcoff_build_ldsyms): ...here. Use XCOFF_WAS_UNDEFINED to
+ check for symbols that were implicitly defined.
+ (xcoff_mark): Don't count any dynamic relocations against
+ function symbols.
+ (bfd_xcoff_size_dynamic_sections): Save the rtld parameter
+ in the xcoff link info.
+ (xcoff_link_input_bfd): Remove handling of undefined and
+ unexported symbols.
+
+2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com>
+
* coff-rs6000.c (xcoff_reloc_type_br): Make the branch absolute
if the target is absolute. Fix comment typo.
(xcoff_ppc_relocate_section): Remove FIXME.
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index 0a849d1..7002485 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -3447,6 +3447,17 @@ xcoff_ppc_relocate_section (output_bfd, info, input_bfd,
}
else
{
+ if (info->unresolved_syms_in_objects != RM_IGNORE
+ && (h->flags & XCOFF_WAS_UNDEFINED) != 0)
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string,
+ input_bfd, input_section,
+ rel->r_vaddr - input_section->vma,
+ (info->unresolved_syms_in_objects
+ == RM_GENERATE_ERROR))))
+ return FALSE;
+ }
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
@@ -3462,17 +3473,11 @@ xcoff_ppc_relocate_section (output_bfd, info, input_bfd,
+ sec->output_offset);
}
- else if ((0 == (h->flags & (XCOFF_DEF_DYNAMIC | XCOFF_IMPORT)))
- && ! info->relocatable)
+ else
{
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd, input_section,
- rel->r_vaddr - input_section->vma, TRUE)))
- return FALSE;
-
- /* Don't try to process the reloc. It can't help, and
- it may generate another error. */
- continue;
+ BFD_ASSERT (info->relocatable
+ || (h->flags & XCOFF_DEF_DYNAMIC) != 0
+ || (h->flags & XCOFF_IMPORT) != 0);
}
}
}
diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c
index 71a02c2..6be1583 100644
--- a/bfd/coff64-rs6000.c
+++ b/bfd/coff64-rs6000.c
@@ -1293,6 +1293,17 @@ xcoff64_ppc_relocate_section (output_bfd, info, input_bfd,
}
else
{
+ if (info->unresolved_syms_in_objects != RM_IGNORE
+ && (h->flags & XCOFF_WAS_UNDEFINED) != 0)
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string,
+ input_bfd, input_section,
+ rel->r_vaddr - input_section->vma,
+ (info->unresolved_syms_in_objects
+ == RM_GENERATE_ERROR))))
+ return FALSE;
+ }
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
@@ -1307,17 +1318,11 @@ xcoff64_ppc_relocate_section (output_bfd, info, input_bfd,
val = (sec->output_section->vma
+ sec->output_offset);
}
- else if ((0 == (h->flags & (XCOFF_DEF_DYNAMIC | XCOFF_IMPORT)))
- && ! info->relocatable)
+ else
{
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd, input_section,
- rel->r_vaddr - input_section->vma, TRUE)))
- return FALSE;
-
- /* Don't try to process the reloc. It can't help, and
- it may generate another error. */
- continue;
+ BFD_ASSERT (info->relocatable
+ || (h->flags & XCOFF_DEF_DYNAMIC) != 0
+ || (h->flags & XCOFF_IMPORT) != 0);
}
}
}
diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index 0a38ac3..d651e3a 100644
--- a/bfd/xcofflink.c
+++ b/bfd/xcofflink.c
@@ -1845,19 +1845,16 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
goto error_return;
}
- /* We identify all symbols which are called, so that we
- can create glue code for calls to functions imported
- from dynamic objects. */
+ /* We identify all function symbols that are the target
+ of a relocation, so that we can create glue code for
+ functions imported from dynamic objects. */
if (info->output_bfd->xvec == abfd->xvec
&& *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;
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
@@ -1890,11 +1887,12 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
hds = (struct xcoff_link_hash_entry *) bh;
}
hds->flags |= XCOFF_DESCRIPTOR;
- BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0
- && (h->flags & XCOFF_DESCRIPTOR) == 0);
+ BFD_ASSERT ((h->flags & XCOFF_DESCRIPTOR) == 0);
hds->descriptor = h;
h->descriptor = hds;
}
+ if (h->root.root.string[0] == '.')
+ h->flags |= XCOFF_CALLED;
}
}
@@ -2203,6 +2201,94 @@ _bfd_xcoff_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
}
}
+/* If symbol H has not been interpreted as a function descriptor,
+ see whether it should be. Set up its descriptor information if so. */
+
+static bfd_boolean
+xcoff_find_function (struct bfd_link_info *info,
+ struct xcoff_link_hash_entry *h)
+{
+ if ((h->flags & XCOFF_DESCRIPTOR) == 0
+ && h->root.root.string[0] != '.')
+ {
+ char *fnname;
+ struct xcoff_link_hash_entry *hfn;
+ bfd_size_type amt;
+
+ amt = strlen (h->root.root.string) + 2;
+ fnname = bfd_malloc (amt);
+ if (fnname == NULL)
+ return FALSE;
+ fnname[0] = '.';
+ strcpy (fnname + 1, h->root.root.string);
+ hfn = xcoff_link_hash_lookup (xcoff_hash_table (info),
+ fnname, FALSE, FALSE, TRUE);
+ free (fnname);
+ if (hfn != NULL
+ && hfn->smclas == XMC_PR
+ && (hfn->root.type == bfd_link_hash_defined
+ || hfn->root.type == bfd_link_hash_defweak))
+ {
+ h->flags |= XCOFF_DESCRIPTOR;
+ h->descriptor = hfn;
+ hfn->descriptor = h;
+ }
+ }
+ return TRUE;
+}
+
+/* H is an imported symbol. Set the import module's path, file and member
+ to IMPATH, IMPFILE and IMPMEMBER respectively. All three are null if
+ no specific import module is specified. */
+
+static bfd_boolean
+xcoff_set_import_path (struct bfd_link_info *info,
+ struct xcoff_link_hash_entry *h,
+ const char *imppath, const char *impfile,
+ const char *impmember)
+{
+ unsigned int c;
+ struct xcoff_import_file **pp;
+
+ /* We overload the ldindx field to hold the l_ifile value for this
+ symbol. */
+ BFD_ASSERT (h->ldsym == NULL);
+ BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0);
+ if (imppath == NULL)
+ h->ldindx = -1;
+ else
+ {
+ /* We start c at 1 because the first entry in the import list is
+ reserved for the library search path. */
+ for (pp = &xcoff_hash_table (info)->imports, c = 1;
+ *pp != NULL;
+ pp = &(*pp)->next, ++c)
+ {
+ if (strcmp ((*pp)->path, imppath) == 0
+ && strcmp ((*pp)->file, impfile) == 0
+ && strcmp ((*pp)->member, impmember) == 0)
+ break;
+ }
+
+ if (*pp == NULL)
+ {
+ struct xcoff_import_file *n;
+ bfd_size_type amt = sizeof (* n);
+
+ n = bfd_alloc (info->output_bfd, amt);
+ if (n == NULL)
+ return FALSE;
+ n->next = NULL;
+ n->path = imppath;
+ n->file = impfile;
+ n->member = impmember;
+ *pp = n;
+ }
+ h->ldindx = c;
+ }
+ return TRUE;
+}
+
/* Mark a symbol as not being garbage, including the section in which
it is defined. */
@@ -2213,6 +2299,136 @@ xcoff_mark_symbol (struct bfd_link_info *info, struct xcoff_link_hash_entry *h)
return TRUE;
h->flags |= XCOFF_MARK;
+
+ /* If we're marking an undefined symbol, try find some way of
+ defining it. */
+ if (!info->relocatable
+ && (h->flags & XCOFF_IMPORT) == 0
+ && (h->flags & XCOFF_DEF_REGULAR) == 0
+ && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak))
+ {
+ /* First check whether this symbol can be interpreted as an
+ undefined function descriptor for a defined function symbol. */
+ if (!xcoff_find_function (info, h))
+ return FALSE;
+
+ if ((h->flags & XCOFF_DESCRIPTOR) != 0
+ && (h->descriptor->root.type == bfd_link_hash_defined
+ || h->descriptor->root.type == bfd_link_hash_defweak))
+ {
+ /* This is a descriptor for a defined symbol, but the input
+ objects have not defined the descriptor itself. Fill in
+ the definition automatically.
+
+ Note that we do this even if we found a dynamic definition
+ of H. The local function definition logically overrides
+ the dynamic one. */
+ asection *sec;
+
+ sec = xcoff_hash_table (info)->descriptor_section;
+ h->root.type = bfd_link_hash_defined;
+ h->root.u.def.section = sec;
+ h->root.u.def.value = sec->size;
+ h->smclas = XMC_DS;
+ h->flags |= XCOFF_DEF_REGULAR;
+
+ /* The size of the function descriptor depends on whether this
+ is xcoff32 (12) or xcoff64 (24). */
+ sec->size += bfd_xcoff_function_descriptor_size (sec->owner);
+
+ /* A function descriptor uses two relocs: one for the
+ associated code, and one for the TOC address. */
+ xcoff_hash_table (info)->ldrel_count += 2;
+ sec->reloc_count += 2;
+
+ /* Mark the function itself. */
+ if (!xcoff_mark_symbol (info, h->descriptor))
+ return FALSE;
+
+ /* We handle writing out the contents of the descriptor in
+ xcoff_write_global_symbol. */
+ }
+ else if ((h->flags & XCOFF_CALLED) != 0)
+ {
+ /* This is a function symbol for which we need to create
+ linkage code. */
+ asection *sec;
+ struct xcoff_link_hash_entry *hds;
+
+ /* Mark the descriptor (and its TOC section). */
+ hds = h->descriptor;
+ BFD_ASSERT ((hds->root.type == bfd_link_hash_undefined
+ || hds->root.type == bfd_link_hash_undefweak)
+ && (hds->flags & XCOFF_DEF_REGULAR) == 0);
+ if (!xcoff_mark_symbol (info, hds))
+ return FALSE;
+
+ /* Treat this symbol as undefined if the descriptor was. */
+ if ((hds->flags & XCOFF_WAS_UNDEFINED) != 0)
+ h->flags |= XCOFF_WAS_UNDEFINED;
+
+ /* Allocate room for the global linkage code itself. */
+ sec = xcoff_hash_table (info)->linkage_section;
+ h->root.type = bfd_link_hash_defined;
+ h->root.u.def.section = sec;
+ h->root.u.def.value = sec->size;
+ h->smclas = XMC_GL;
+ h->flags |= XCOFF_DEF_REGULAR;
+ sec->size += bfd_xcoff_glink_code_size (info->output_bfd);
+
+ /* The global linkage code requires a TOC entry for the
+ descriptor. */
+ if (hds->toc_section == NULL)
+ {
+ int byte_size;
+
+ /* 32 vs 64
+ xcoff32 uses 4 bytes in the toc.
+ xcoff64 uses 8 bytes in the toc. */
+ if (bfd_xcoff_is_xcoff64 (info->output_bfd))
+ byte_size = 8;
+ else if (bfd_xcoff_is_xcoff32 (info->output_bfd))
+ byte_size = 4;
+ else
+ return FALSE;
+
+ /* Allocate room in the fallback TOC section. */
+ hds->toc_section = xcoff_hash_table (info)->toc_section;
+ hds->u.toc_offset = hds->toc_section->size;
+ hds->toc_section->size += byte_size;
+ if (!xcoff_mark (info, hds->toc_section))
+ return FALSE;
+
+ /* Allocate room for a static and dynamic R_TOC
+ relocation. */
+ ++xcoff_hash_table (info)->ldrel_count;
+ ++hds->toc_section->reloc_count;
+
+ /* Set the index to -2 to force this symbol to
+ get written out. */
+ hds->indx = -2;
+ hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
+ }
+ }
+ else if ((h->flags & XCOFF_DEF_DYNAMIC) == 0)
+ {
+ /* Record that the symbol was undefined, then import it.
+ -brtl links use a special fake import file. */
+ h->flags |= XCOFF_WAS_UNDEFINED | XCOFF_IMPORT;
+ if (xcoff_hash_table (info)->rtld)
+ {
+ if (!xcoff_set_import_path (info, h, "", "..", ""))
+ return FALSE;
+ }
+ else
+ {
+ if (!xcoff_set_import_path (info, h, NULL, NULL, NULL))
+ return FALSE;
+ }
+ }
+ }
+
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
@@ -2320,15 +2536,9 @@ xcoff_mark (struct bfd_link_info *info, asection *sec)
|| h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak
|| h->root.type == bfd_link_hash_common
- || ((h->flags & XCOFF_CALLED) != 0
- && (h->root.type == bfd_link_hash_undefined
- || h->root.type == bfd_link_hash_undefweak)
- && h->root.root.string[0] == '.'
- && h->descriptor != NULL
- && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
- || ((h->descriptor->flags & XCOFF_IMPORT) != 0
- && (h->descriptor->flags
- & XCOFF_DEF_REGULAR) == 0))))
+ /* We will always provide a local definition of
+ function symbols. */
+ || (h->flags & XCOFF_CALLED) != 0)
break;
/* Fall through. */
case R_POS:
@@ -2483,8 +2693,7 @@ bfd_xcoff_import_symbol (bfd *output_bfd,
hds->root.u.undef.abfd = h->root.u.undef.abfd;
}
hds->flags |= XCOFF_DESCRIPTOR;
- BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0
- && (h->flags & XCOFF_DESCRIPTOR) == 0);
+ BFD_ASSERT ((h->flags & XCOFF_DESCRIPTOR) == 0);
hds->descriptor = h;
h->descriptor = hds;
}
@@ -2516,46 +2725,8 @@ bfd_xcoff_import_symbol (bfd *output_bfd,
h->root.u.def.value = val;
}
- /* We overload the ldindx field to hold the l_ifile value for this
- symbol. */
- BFD_ASSERT (h->ldsym == NULL);
- BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0);
- if (imppath == NULL)
- h->ldindx = -1;
- else
- {
- unsigned int c;
- struct xcoff_import_file **pp;
-
- /* We start c at 1 because the first entry in the import list is
- reserved for the library search path. */
- for (pp = &xcoff_hash_table (info)->imports, c = 1;
- *pp != NULL;
- pp = &(*pp)->next, ++c)
- {
- if (strcmp ((*pp)->path, imppath) == 0
- && strcmp ((*pp)->file, impfile) == 0
- && strcmp ((*pp)->member, impmember) == 0)
- break;
- }
-
- if (*pp == NULL)
- {
- struct xcoff_import_file *n;
- bfd_size_type amt = sizeof (* n);
-
- n = bfd_alloc (output_bfd, amt);
- if (n == NULL)
- return FALSE;
- n->next = NULL;
- n->path = imppath;
- n->file = impfile;
- n->member = impmember;
- *pp = n;
- }
-
- h->ldindx = c;
- }
+ if (!xcoff_set_import_path (info, h, imppath, impfile, impmember))
+ return FALSE;
return TRUE;
}
@@ -2577,34 +2748,6 @@ bfd_xcoff_export_symbol (bfd *output_bfd,
/* FIXME: I'm not at all sure what syscall is supposed to mean, so
I'm just going to ignore it until somebody explains it. */
- /* See if this is a function descriptor. It may be one even though
- it is not so marked. */
- if ((h->flags & XCOFF_DESCRIPTOR) == 0
- && h->root.root.string[0] != '.')
- {
- char *fnname;
- struct xcoff_link_hash_entry *hfn;
- bfd_size_type amt = strlen (h->root.root.string) + 2;
-
- fnname = bfd_malloc (amt);
- if (fnname == NULL)
- return FALSE;
- fnname[0] = '.';
- strcpy (fnname + 1, h->root.root.string);
- hfn = xcoff_link_hash_lookup (xcoff_hash_table (info),
- fnname, FALSE, FALSE, TRUE);
- free (fnname);
- if (hfn != NULL
- && hfn->smclas == XMC_PR
- && (hfn->root.type == bfd_link_hash_defined
- || hfn->root.type == bfd_link_hash_defweak))
- {
- h->flags |= XCOFF_DESCRIPTOR;
- h->descriptor = hfn;
- hfn->descriptor = h;
- }
- }
-
/* Make sure we don't garbage collect this symbol. */
if (! xcoff_mark_symbol (info, h))
return FALSE;
@@ -2767,115 +2910,16 @@ xcoff_build_ldsyms (struct xcoff_link_hash_entry *h, void * p)
!= ldinfo->info->output_bfd->xvec)))
h->flags |= XCOFF_MARK;
- /* If this symbol is called and defined in a dynamic object, or it
- is imported, then we need to set up global linkage code for it.
- (Unless we did garbage collection and we didn't need this
- symbol.) */
- if ((h->flags & XCOFF_CALLED) != 0
- && (h->root.type == bfd_link_hash_undefined
- || h->root.type == bfd_link_hash_undefweak)
- && h->root.root.string[0] == '.'
- && h->descriptor != NULL
- && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
- || ((h->descriptor->flags & XCOFF_IMPORT) != 0
- && (h->descriptor->flags & XCOFF_DEF_REGULAR) == 0))
- && (! xcoff_hash_table (ldinfo->info)->gc
- || (h->flags & XCOFF_MARK) != 0))
- {
- asection *sec;
- struct xcoff_link_hash_entry *hds;
-
- sec = xcoff_hash_table (ldinfo->info)->linkage_section;
- h->root.type = bfd_link_hash_defined;
- h->root.u.def.section = sec;
- h->root.u.def.value = sec->size;
- h->smclas = XMC_GL;
- h->flags |= XCOFF_DEF_REGULAR;
- sec->size += bfd_xcoff_glink_code_size(ldinfo->output_bfd);
-
- /* The global linkage code requires a TOC entry for the
- descriptor. */
- hds = h->descriptor;
- BFD_ASSERT ((hds->root.type == bfd_link_hash_undefined
- || hds->root.type == bfd_link_hash_undefweak)
- && (hds->flags & XCOFF_DEF_REGULAR) == 0);
- hds->flags |= XCOFF_MARK;
- if (hds->toc_section == NULL)
- {
- int byte_size;
-
- /* 32 vs 64
- 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;
- else if (bfd_xcoff_is_xcoff32 (ldinfo->output_bfd))
- byte_size = 4;
- else
- return FALSE;
-
- hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
- hds->u.toc_offset = hds->toc_section->size;
- hds->toc_section->size += byte_size;
- ++xcoff_hash_table (ldinfo->info)->ldrel_count;
- ++hds->toc_section->reloc_count;
- hds->indx = -2;
- hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
-
- /* We need to call xcoff_build_ldsyms recursively here,
- because we may already have passed hds on the traversal. */
- xcoff_build_ldsyms (hds, p);
- }
- }
-
/* If this symbol is exported, but not defined, we need to try to
define it. */
if ((h->flags & XCOFF_EXPORT) != 0
- && (h->flags & XCOFF_IMPORT) == 0
- && (h->flags & XCOFF_DEF_REGULAR) == 0
- && (h->flags & XCOFF_DEF_DYNAMIC) == 0
- && (h->root.type == bfd_link_hash_undefined
- || h->root.type == bfd_link_hash_undefweak))
+ && (h->flags & XCOFF_WAS_UNDEFINED) != 0)
{
- if ((h->flags & XCOFF_DESCRIPTOR) != 0
- && (h->descriptor->root.type == bfd_link_hash_defined
- || h->descriptor->root.type == bfd_link_hash_defweak))
- {
- asection *sec;
-
- /* This is an undefined function descriptor associated with
- a defined entry point. We can build up a function
- descriptor ourselves. Believe it or not, the AIX linker
- actually does this, and there are cases where we need to
- do it as well. */
- sec = xcoff_hash_table (ldinfo->info)->descriptor_section;
- h->root.type = bfd_link_hash_defined;
- h->root.u.def.section = sec;
- h->root.u.def.value = sec->size;
- h->smclas = XMC_DS;
- h->flags |= XCOFF_DEF_REGULAR;
-
- /* The size of the function descriptor depends if this is an
- xcoff32 (12) or xcoff64 (24). */
- sec->size +=
- bfd_xcoff_function_descriptor_size(ldinfo->output_bfd);
-
- /* A function descriptor uses two relocs: one for the
- associated code, and one for the TOC address. */
- xcoff_hash_table (ldinfo->info)->ldrel_count += 2;
- sec->reloc_count += 2;
-
- /* We handle writing out the contents of the descriptor in
- xcoff_write_global_symbol. */
- }
- else
- {
- (*_bfd_error_handler)
- (_("warning: attempt to export undefined symbol `%s'"),
- h->root.root.string);
- h->ldsym = NULL;
- return TRUE;
- }
+ (*_bfd_error_handler)
+ (_("warning: attempt to export undefined symbol `%s'"),
+ h->root.root.string);
+ h->ldsym = NULL;
+ return TRUE;
}
/* If this is still a common symbol, and it wasn't garbage
@@ -3017,6 +3061,7 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
xcoff_hash_table (info)->file_align = file_align;
xcoff_hash_table (info)->textro = textro;
+ xcoff_hash_table (info)->rtld = rtld;
hentry = NULL;
if (entry != NULL)
@@ -4318,7 +4363,6 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
{
struct xcoff_link_hash_entry *h = NULL;
struct internal_ldrel ldrel;
- bfd_boolean quiet;
*rel_hash = NULL;
@@ -4451,7 +4495,6 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
}
}
- quiet = FALSE;
switch (irel->r_type)
{
default:
@@ -4507,17 +4550,7 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
}
else
{
- if (! finfo->info->relocatable
- && (h->flags & XCOFF_DEF_DYNAMIC) == 0
- && (h->flags & XCOFF_IMPORT) == 0)
- {
- /* We already called the undefined_symbol
- callback for this relocation, in
- _bfd_ppc_xcoff_relocate_section. Don't
- issue any more warnings. */
- quiet = TRUE;
- }
- if (h->ldindx < 0 && ! quiet)
+ if (h->ldindx < 0)
{
(*_bfd_error_handler)
(_("%B: `%s' in loader reloc but not loader sym"),
@@ -4531,8 +4564,7 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
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
- && strcmp (o->output_section->name, ".text") == 0
- && ! quiet)
+ && strcmp (o->output_section->name, ".text") == 0)
{
(*_bfd_error_handler)
(_("%B: loader reloc in read-only section %A"),
diff --git a/include/coff/ChangeLog b/include/coff/ChangeLog
index 53bf7e5..91118a1 100644
--- a/include/coff/ChangeLog
+++ b/include/coff/ChangeLog
@@ -1,3 +1,9 @@
+2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ * xcoff.h (XCOFF_CALLED, XCOFF_IMPORT): Update comments.
+ (XCOFF_WAS_UNDEFINED): New flag.
+ (xcoff_link_hash_table): Add an "rtld" field.
+
2008-12-23 Johan Olmutz Nielsen <jnielsen@ddci.com>
* ti.h (COFF_ADJUST_SCNHDR_OUT_PRE): Define.
diff --git a/include/coff/xcoff.h b/include/coff/xcoff.h
index 7c1eef5..7e32d7a 100644
--- a/include/coff/xcoff.h
+++ b/include/coff/xcoff.h
@@ -291,11 +291,12 @@ struct xcoff_link_hash_entry
#define XCOFF_LDREL 0x00000008
/* Symbol is the entry point. */
#define XCOFF_ENTRY 0x00000010
-/* Symbol is called; this is, it appears in a R_BR reloc. */
+/* Symbol is for a function and is the target of a relocation.
+ The relocation may or may not be a branch-type relocation. */
#define XCOFF_CALLED 0x00000020
/* Symbol needs the TOC entry filled in. */
#define XCOFF_SET_TOC 0x00000040
-/* Symbol is explicitly imported. */
+/* Symbol is implicitly or explicitly imported. */
#define XCOFF_IMPORT 0x00000080
/* Symbol is explicitly exported. */
#define XCOFF_EXPORT 0x00000100
@@ -315,6 +316,8 @@ struct xcoff_link_hash_entry
#define XCOFF_SYSCALL32 0x00008000
/* Symbol is an imported 64 bit syscall. */
#define XCOFF_SYSCALL64 0x00010000
+/* Symbol was not explicitly defined by the time it was marked. */
+#define XCOFF_WAS_UNDEFINED 0x00020000
/* The XCOFF linker hash table. */
@@ -368,6 +371,9 @@ struct xcoff_link_hash_table
/* Whether the .text section must be read-only. */
bfd_boolean textro;
+ /* Whether -brtl was specified. */
+ bfd_boolean rtld;
+
/* Whether garbage collection was done. */
bfd_boolean gc;
diff --git a/ld/ChangeLog b/ld/ChangeLog
index fb3b552..40434eb 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,12 @@
2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com>
+ * emultempl/aix.em (gld${EMULATION_NAME}_handle_option): Make
+ -berok and -bernotok control link_info.unresolved_syms_in_objects
+ and link_info.unresolved_syms_in_shared_libs instead of
+ force_make_executable.
+
+2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com>
+
* emultempl/aix.em (gld${EMULATION_NAME}_before_parse): Set
config.dynamic_link to TRUE.
diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em
index 90465f2..a9f3884 100644
--- a/ld/emultempl/aix.em
+++ b/ld/emultempl/aix.em
@@ -379,11 +379,13 @@ gld${EMULATION_NAME}_handle_option (int optc)
break;
case OPTION_ERNOTOK:
- force_make_executable = FALSE;
+ link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
+ link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR;
break;
case OPTION_EROK:
- force_make_executable = TRUE;
+ link_info.unresolved_syms_in_objects = RM_IGNORE;
+ link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
break;
case OPTION_EXPORT:
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 55e3a92..bc20d02 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,5 +1,12 @@
2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com>
+ * ld-powerpc/aix-glink-1.ex, ld-powerpc/aix-glink-1.s,
+ ld-powerpc/aix-glink-1-32.dd, ld-powerpc/aix-glink-1-64.dd,
+ ld-powerpc/aix-glink-1-32.d, ld-powerpc/aix-glink-1-64.d: New tests.
+ * ld-powerpc/aix52.exp: Run them.
+
+2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com>
+
* ld-powerpc/aix-abs-branch-1.im, ld-powerpc/aix-abs-branch-1.ex,
ld-powerpc/aix-abs-branch-1.s,
ld-powerpc/aix-abs-branch-1.dd: New test.
diff --git a/ld/testsuite/ld-powerpc/aix-glink-1-32.d b/ld/testsuite/ld-powerpc/aix-glink-1-32.d
new file mode 100644
index 0000000..129845f
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-1-32.d
@@ -0,0 +1,5 @@
+#name: Glink test 1 (error) (32-bit)
+#source: aix-glink-1.s
+#as: -a32
+#ld: -b32 -bM:SRE -bnogc
+#error: undefined reference to `\.ext'
diff --git a/ld/testsuite/ld-powerpc/aix-glink-1-32.dd b/ld/testsuite/ld-powerpc/aix-glink-1-32.dd
new file mode 100644
index 0000000..33cf812
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-1-32.dd
@@ -0,0 +1,44 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+10000000 <\.f1>:
+10000000: 4e 80 00 20 br
+
+10000004 <\.f2>:
+10000004: 48 00 00 05 bl 10000008 <\.f3>
+
+10000008 <\.f3>:
+10000008: 4e 80 00 20 br
+
+1000000c <\.ext>:
+1000000c: 81 82 00 00 l r12,0\(r2\)
+10000010: 90 41 00 14 st r2,20\(r1\)
+10000014: 80 0c 00 00 l r0,0\(r12\)
+10000018: 80 4c 00 04 l r2,4\(r12\)
+1000001c: 7c 09 03 a6 mtctr r0
+10000020: 4e 80 04 20 bctr
+10000024: 00 00 00 00 \.long 0x0
+10000028: 00 0c 80 00 \.long 0xc8000
+1000002c: 00 00 00 00 \.long 0x0
+
+Disassembly of section \.data:
+
+20000000 <foo>:
+20000000: 20 00 00 08 .*
+20000004: 10 00 00 0c .*
+
+20000008 <f1>:
+20000008: 10 00 00 00 .*
+2000000c: 20 00 00 20 .*
+20000010: 00 00 00 00 .*
+
+20000014 <f2>:
+20000014: 10 00 00 04 .*
+20000018: 20 00 00 20 .*
+2000001c: 00 00 00 00 .*
+
+20000020 <TOC>:
+ \.\.\.
diff --git a/ld/testsuite/ld-powerpc/aix-glink-1-64.d b/ld/testsuite/ld-powerpc/aix-glink-1-64.d
new file mode 100644
index 0000000..b8ee35f
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-1-64.d
@@ -0,0 +1,5 @@
+#name: Glink test 1 (error) (64-bit)
+#source: aix-glink-1.s
+#as: -a64
+#ld: -b64 -bM:SRE -bnogc
+#error: undefined reference to `\.ext'
diff --git a/ld/testsuite/ld-powerpc/aix-glink-1-64.dd b/ld/testsuite/ld-powerpc/aix-glink-1-64.dd
new file mode 100644
index 0000000..b5a557c
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-1-64.dd
@@ -0,0 +1,49 @@
+
+.*
+
+
+Disassembly of section \.text:
+
+0000000010000000 <\.f1>:
+ 10000000: 4e 80 00 20 blr
+
+0000000010000004 <\.f2>:
+ 10000004: 48 00 00 05 bl 10000008 <\.f3>
+
+0000000010000008 <\.f3>:
+ 10000008: 4e 80 00 20 blr
+
+000000001000000c <\.ext>:
+ 1000000c: e9 82 00 00 ld r12,0\(r2\)
+ 10000010: f8 41 00 28 std r2,40\(r1\)
+ 10000014: e8 0c 00 00 ld r0,0\(r12\)
+ 10000018: e8 4c 00 08 ld r2,8\(r12\)
+ 1000001c: 7c 09 03 a6 mtctr r0
+ 10000020: 4e 80 04 20 bctr
+ 10000024: 00 00 00 00 \.long 0x0
+ 10000028: 00 0c a0 00 \.long 0xca000
+ 1000002c: 00 00 00 00 \.long 0x0
+ 10000030: 00 00 00 18 \.long 0x18
+
+Disassembly of section \.data:
+
+0000000020000000 <foo>:
+ 20000000: 20 00 00 08 .*
+ 20000004: 10 00 00 0c .*
+
+0000000020000008 <f1>:
+ 20000008: 00 00 00 00 .*
+ 2000000c: 10 00 00 00 .*
+ 20000010: 00 00 00 00 .*
+ 20000014: 20 00 00 38 .*
+ \.\.\.
+
+0000000020000020 <f2>:
+ 20000020: 00 00 00 00 .*
+ 20000024: 10 00 00 04 .*
+ 20000028: 00 00 00 00 .*
+ 2000002c: 20 00 00 38 .*
+ \.\.\.
+
+0000000020000038 <TOC>:
+ \.\.\.
diff --git a/ld/testsuite/ld-powerpc/aix-glink-1.ex b/ld/testsuite/ld-powerpc/aix-glink-1.ex
new file mode 100644
index 0000000..643cdf3
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-1.ex
@@ -0,0 +1,2 @@
+f2
+foo
diff --git a/ld/testsuite/ld-powerpc/aix-glink-1.s b/ld/testsuite/ld-powerpc/aix-glink-1.s
new file mode 100644
index 0000000..f7901b2
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/aix-glink-1.s
@@ -0,0 +1,21 @@
+ .toc
+ .globl .f1
+ .csect .f1[PR]
+.f1:
+ blr
+
+ .globl .f2
+ .csect .f2[PR]
+.f2:
+ bl .f3
+
+ .globl .f3
+ .csect .f3[PR]
+.f3:
+ blr
+
+ .globl foo
+ .csect foo[RW]
+foo:
+ .long f1
+ .long .ext
diff --git a/ld/testsuite/ld-powerpc/aix52.exp b/ld/testsuite/ld-powerpc/aix52.exp
index 632d0b9..41a2045 100644
--- a/ld/testsuite/ld-powerpc/aix52.exp
+++ b/ld/testsuite/ld-powerpc/aix52.exp
@@ -91,6 +91,12 @@ set aix52tests {
"" {aix-core-sec-3.s}
{{objdump -h aix-core-sec-3.hd}}
"aix-core-sec-3.so"}
+
+ {"Glink test 1"
+ "-shared -bE:aix-glink-1.ex --unresolved-symbols=ignore-all"
+ "" {aix-glink-1.s}
+ {{objdump {-D -j.text -j.data} aix-glink-1-SIZE.dd}}
+ "aix-glink-1.so"}
}
foreach test $aix52tests {