This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[9/21] Implicitly import undefined symbols


This patch fixes three related problems:

  (1) If a function symbol .FOO is defined but its descriptor FOO is not,
      the linker creates an automatic definition itself.  However, it
      currently only does this if FOO is exported, whereas the AIX
      linker does it for internal references too.  That is, if you have:

		.csect .FOO[PR]
	.FOO:
		...
		.long	FOO

      the AIX linker automatically creates FOO if necessary.

      This might well just be cleaning up after forgetful assembler
      programmers, but *shuffle* we did stumble across this the hard way...

  (2) The linker is inconsistent in the way it handles:

		.long	.FOO

      for an external function FOO.  If FOO is also called, such as by:

		bl      .FOO

      the linker creates global linkage code for FOO and redirects
      _both_ relocations to it.  However, if FOO isn't called, the
      linker generates a dynamic relocation against .FOO itself.

      Again, I'm not sure if these sorts of .longs are really suppoesed
      to exist.  Certainly normal function pointers should use the
      function descriptor instead, and I only came across this case
      by inspection, not in real code.  However, the AIX linker redirects
      ".long .FOO" to global linkage code even if there's no "bl .FOO".
      That seems more consistent than our behaviour, and avoids having
      (unresolvable) dynamic relocations against function symbols.

      As an added bonus, it makes the code simpler.

  (3) The most important one.  Let's suppose we have an undefined
      symbol S.  The default -shared behaviour is to allow references
      to S.  However, although we list S in the dynamic (.loader) symbol
      table, we currently don't mark it as imported.  This causes the
      runtime linker to complain that the relocation is against an
      undefined symbol.

      By default, the native AIX linker lists S as an import without
      specifying an import module.  With -brtl, it instead imports S
      with a special filename of "..".  We should do the same.

The patch makes sure that we have a known source for every marked symbol.
If we mark a symbol S that has no current definition, we do one of
three things:

  (a) If S is a function descriptor for a defined function .S, we create
      S automatically.  This is (1) above, and the code is taken from
      xcoff_build_ldsyms.

  (b) If S is a function symbol, we mark its descriptor and create
      global linkage code.  The code for this is taken from
      xcoff_build_ldsyms.

  (c) Otherwise, we implicitly mark the symbol as an import.

(a) is not an error; the AIX linker does not warn about it.  However,
for (c), we need some way of recording that this import was implicit,
so that we still report relocations against it.  The patch adds an
XCOFF_WAS_UNDEFINED flag for this.  It's convenient to set the flag
for (b) too, so that a relocation is against an undefined symbol iff
XCOFF_WAS_UNDEFINED is set.

That deals with (1) and (3) above.  (2) comes into play because of (b).
At the moment, if we see a branch relocation against .S, and if symbol
S does not yet exist, we create an entry for S automatically.  We then
mark S as the descriptor for .S.  However, we don't do this for other
relocations against .S.

So how should we handle .S if it is only referenced by non-branch
relocations?  We could add special code for this case, or we could
treat all relocs in the same way.

The second behaviour is obviously simpler, and is what the native AIX
linker does.  The patch therefore does it too.  XCOFF_CALLED now means
"this is a _function_ symbol that has at least one relocation against it",
rather than its current meaning of "this is a symbol that has at least
one _branch_ relocation against it".  I couldn't think of a better name
for the flag though; the old one still seems appropriate.

Finally, the native AIX linker defines -berok as follows:

    Produces the output object file without errors even if there are
    unresolved external references.

where "without errors" means "silently".  Errors not related to
undefined externs should still be reported.

In contrast, we currently implement -berok as "report errors as normal,
but generate the executable regardless".  The patch makes us follow
the AIX behaviour.

OK to install?

Richard


include/coff/
	* 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.

Index: include/coff/xcoff.h
===================================================================
--- include/coff/xcoff.h	2009-03-10 13:38:53.000000000 +0000
+++ include/coff/xcoff.h	2009-03-10 13:46:23.000000000 +0000
@@ -291,11 +291,12 @@ #define XCOFF_DEF_DYNAMIC      0x0000000
 #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 @@ #define XCOFF_RTINIT           0x0000400
 #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: bfd/coff-rs6000.c
===================================================================
--- bfd/coff-rs6000.c	2009-03-10 13:46:00.000000000 +0000
+++ bfd/coff-rs6000.c	2009-03-10 13:46:23.000000000 +0000
@@ -3447,6 +3447,17 @@ xcoff_ppc_relocate_section (output_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, 
 			 + 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: bfd/coff64-rs6000.c
===================================================================
--- bfd/coff64-rs6000.c	2009-03-10 13:46:00.000000000 +0000
+++ bfd/coff64-rs6000.c	2009-03-10 13:46:23.000000000 +0000
@@ -1293,6 +1293,17 @@ xcoff64_ppc_relocate_section (output_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
 		  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: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c	2009-03-10 13:43:53.000000000 +0000
+++ bfd/xcofflink.c	2009-03-10 13:46:23.000000000 +0000
@@ -1845,19 +1845,16 @@ #define N_BTSHFT n_btshft
 		  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 @@ #define N_BTSHFT n_btshft
 			  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 *ab
     }
 }
 
+/* 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 
     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, 
 		      || 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_ha
 	      != 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 *ou
 
   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 @@ #define N_BTSHFT n_btshft
 	    {
 	      struct xcoff_link_hash_entry *h = NULL;
 	      struct internal_ldrel ldrel;
-	      bfd_boolean quiet;
 
 	      *rel_hash = NULL;
 
@@ -4451,7 +4495,6 @@ #define N_BTSHFT n_btshft
 		    }
 		}
 
-	      quiet = FALSE;
 	      switch (irel->r_type)
 		{
 		default:
@@ -4507,17 +4550,7 @@ #define N_BTSHFT n_btshft
 		    }
 		  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 @@ #define N_BTSHFT n_btshft
 		  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: ld/emultempl/aix.em
===================================================================
--- ld/emultempl/aix.em	2009-03-10 13:43:34.000000000 +0000
+++ ld/emultempl/aix.em	2009-03-10 13:46:23.000000000 +0000
@@ -379,11 +379,13 @@ gld${EMULATION_NAME}_handle_option (int 
       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: ld/testsuite/ld-powerpc/aix-glink-1.ex
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1.ex	2009-03-10 13:46:23.000000000 +0000
@@ -0,0 +1,2 @@
+f2
+foo
Index: ld/testsuite/ld-powerpc/aix-glink-1.s
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1.s	2009-03-10 13:46:23.000000000 +0000
@@ -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: ld/testsuite/ld-powerpc/aix-glink-1-32.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1-32.dd	2009-03-10 13:46:23.000000000 +0000
@@ -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>:
+	\.\.\.
Index: ld/testsuite/ld-powerpc/aix-glink-1-64.dd
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1-64.dd	2009-03-10 13:46:23.000000000 +0000
@@ -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>:
+	\.\.\.
Index: ld/testsuite/ld-powerpc/aix-glink-1-32.d
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1-32.d	2009-03-10 13:46:23.000000000 +0000
@@ -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'
Index: ld/testsuite/ld-powerpc/aix-glink-1-64.d
===================================================================
--- /dev/null	2009-02-06 09:11:03.343159000 +0000
+++ ld/testsuite/ld-powerpc/aix-glink-1-64.d	2009-03-10 13:46:23.000000000 +0000
@@ -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'
Index: ld/testsuite/ld-powerpc/aix52.exp
===================================================================
--- ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:46:00.000000000 +0000
+++ ld/testsuite/ld-powerpc/aix52.exp	2009-03-10 13:46:23.000000000 +0000
@@ -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 {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]