include/coff/
authorRichard Sandiford <rdsandiford@googlemail.com>
Sat, 14 Mar 2009 09:17:32 +0000 (09:17 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Sat, 14 Mar 2009 09:17:32 +0000 (09:17 +0000)
* xcoff.h (XCOFF_CALLED, XCOFF_IMPORT): Update comments.
(XCOFF_WAS_UNDEFINED): New flag.
(xcoff_link_hash_table): Add an "rtld" field.

bfd/
* 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.

ld/
* 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.

ld/testsuite/
* 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.

16 files changed:
bfd/ChangeLog
bfd/coff-rs6000.c
bfd/coff64-rs6000.c
bfd/xcofflink.c
include/coff/ChangeLog
include/coff/xcoff.h
ld/ChangeLog
ld/emultempl/aix.em
ld/testsuite/ChangeLog
ld/testsuite/ld-powerpc/aix-glink-1-32.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-glink-1-32.dd [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-glink-1-64.d [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-glink-1-64.dd [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-glink-1.ex [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix-glink-1.s [new file with mode: 0644]
ld/testsuite/ld-powerpc/aix52.exp

index 818054cf0a093314f729ee16340bab0f404f2e28..477d2f7af5a272f094eb51544f91d8a6a61ed3c9 100644 (file)
@@ -1,3 +1,33 @@
+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
index 0a849d1f75acfacb84542a2608ca7caa5680075d..70024851ec6f673dc159b3e43fbd7c42fcea73ac 100644 (file)
@@ -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);
                }
            }
        }
index 71a02c237beb012098d6c478b46f07c7baa94a70..6be1583a4be1e74e6099543e62f040cdae554252 100644 (file)
@@ -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);
                }
            }
        }
index 0a38ac343c9fbf5e695e60f239b2ddb128ae69f0..d651e3a323a0d750dc656b7049b3129f9aa1e555 100644 (file)
@@ -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)
     }
 }
 \f
+/* 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;
+}
+\f
 /* 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"),
index 53bf7e51178cd44539e21af39efaa884cea2fbea..91118a1a75a5733dc90ca29f9e423cd09babd765 100644 (file)
@@ -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.
index 7c1eef53acabcf076dad7aacc7231af4eed15fe6..7e32d7a7805ad07c087c8fce4651098add848773 100644 (file)
@@ -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;
 
index fb3b5526360693938490c83fcc700159ccff5e36..40434ebe769555ac84cfb8ad1e89fb06722e0b60 100644 (file)
@@ -1,3 +1,10 @@
+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
index 90465f2872c2f858bb6e9d10a48341d0af9e07da..a9f3884055135d8d076215bf3f68e5d32536a349 100644 (file)
@@ -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:
index 55e3a9237c1f897bba0a215177c5f8f25dd8bf41..bc20d02ce43eaa2e7dc986746171498b0ea5b77c 100644 (file)
@@ -1,3 +1,10 @@
+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,
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 (file)
index 0000000..129845f
--- /dev/null
@@ -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 (file)
index 0000000..33cf812
--- /dev/null
@@ -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 (file)
index 0000000..b8ee35f
--- /dev/null
@@ -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 (file)
index 0000000..b5a557c
--- /dev/null
@@ -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 (file)
index 0000000..643cdf3
--- /dev/null
@@ -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 (file)
index 0000000..f7901b2
--- /dev/null
@@ -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
index 632d0b9cd19c190ce029ac087315a2efed4889bb..41a204564c48604b3b80fb99d90a554354faf00d 100644 (file)
@@ -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 {