Patchwork fix PR51910, take 2

login
register
mail settings
Submitter Sandra Loosemore
Date Feb. 3, 2012, 4:10 a.m.
Message ID <4F2B5E4A.50401@codesourcery.com>
Download mbox | patch
Permalink /patch/139295/
State New
Headers show

Comments

Sandra Loosemore - Feb. 3, 2012, 4:10 a.m.
Here is another attempt to fix the bad interaction between 
--with-demangler-in-ld and -frepo processing.

This version of the patch always disables demangling in ld when 
repository files are present for the link.  If demangling is requested 
(either by an explicit -Wl,--demangle option, by using 
COLLECT_NO_DEMANGLE, or just doing nothing and getting the default), 
it'll be performed by having collect2 filter the output streams no 
matter how you configured --with-demangler-in-ld.  The exception is if 
-Wl,-Map is also provided, in which case it falls back on re-running the 
final link with the correct options to get a demangled map file after it 
is done with the repo file processing.

I could have implemented that last bit by having collect2 intercept the 
map file option and filter the file to demangle it, and make that the 
default behavior when collect2 is otherwise doing demangling itself. 
Given the previous argument that users can't possibly have any reason to 
want a demangled link map, I thought there might be objection to 
polluting collect2 by hacking it up to do just that.  I mean, it's 
horrible enough that ld produces a demangled map file when you request 
demangled output....  :-P

Anyway, thoughts on this patch?  It bootstrapped and regression tested 
OK on i686-linux, and I hand-tested it on every permutation of 
mangling/repository/map options I could think of.

-Sandra


2012-02-02  Sandra Loosemore <sandra@codesourcery.com>
	    Jason Merrill <jason@redhat.com>
	    Jakub Jelinek <jakub@redhat.com>

	PR c++/51910
	gcc/
	* collect2.c (dump_file): Add demangle_in_ld parameter so this
	can be tested dynamically instead only at compile-time.  Update
	callers.
	(main): Initialize no_demangle even when HAVE_LD_DEMANGLE.
	* collect2.h (dump_file): Adjust declaration.
	(no_demangle): Delare as extern.
	(DEMANGLE_IN_LD): Define.
	* tlink.c (do_tlink): Explicitly pass --no-demangle to linker
	for repo processing when HAVE_LD_DEMANGLE is defined, and demangle
	in collect2 instead of the linker.

	gcc/testsuite/
	* g++.dg/torture/pr51910.C: New testcase.

Patch

Index: gcc/collect2.c
===================================================================
--- gcc/collect2.c	(revision 183674)
+++ gcc/collect2.c	(working copy)
@@ -403,13 +403,13 @@  collect_exit (int status)
 
   if (ldout != 0 && ldout[0])
     {
-      dump_file (ldout, stdout);
+      dump_file (ldout, stdout, DEMANGLE_IN_LD);
       maybe_unlink (ldout);
     }
 
   if (lderrout != 0 && lderrout[0])
     {
-      dump_file (lderrout, stderr);
+      dump_file (lderrout, stderr, DEMANGLE_IN_LD);
       maybe_unlink (lderrout);
     }
 
@@ -515,7 +515,7 @@  extract_string (const char **pp)
 }
 
 void
-dump_file (const char *name, FILE *to)
+dump_file (const char *name, FILE *to, int demangle_in_ld)
 {
   FILE *stream = fopen (name, "r");
 
@@ -540,14 +540,10 @@  dump_file (const char *name, FILE *to)
 	  if (!strncmp (p, USER_LABEL_PREFIX, strlen (USER_LABEL_PREFIX)))
 	    p += strlen (USER_LABEL_PREFIX);
 
-#ifdef HAVE_LD_DEMANGLE
-	  result = 0;
-#else
-	  if (no_demangle)
+	  if (no_demangle || demangle_in_ld)
 	    result = 0;
 	  else
 	    result = cplus_demangle (p, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
-#endif
 
 	  if (result)
 	    {
@@ -1114,9 +1110,8 @@  main (int argc, char **argv)
 
   num_c_args = argc + 9;
 
-#ifndef HAVE_LD_DEMANGLE
   no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
-
+#ifndef HAVE_LD_DEMANGLE
   /* Suppress demangling by the real linker, which may be broken.  */
   putenv (xstrdup ("COLLECT_NO_DEMANGLE=1"));
 #endif
@@ -1566,15 +1561,14 @@  main (int argc, char **argv)
 	    case '-':
 	      if (strcmp (arg, "--no-demangle") == 0)
 		{
-#ifndef HAVE_LD_DEMANGLE
 		  no_demangle = 1;
+#ifndef HAVE_LD_DEMANGLE
 		  ld1--;
 		  ld2--;
 #endif
 		}
 	      else if (strncmp (arg, "--demangle", 10) == 0)
 		{
-#ifndef HAVE_LD_DEMANGLE
 		  no_demangle = 0;
 		  if (arg[10] == '=')
 		    {
@@ -1585,6 +1579,7 @@  main (int argc, char **argv)
 		      else
 			current_demangling_style = style;
 		    }
+#ifndef HAVE_LD_DEMANGLE
 		  ld1--;
 		  ld2--;
 #endif
Index: gcc/collect2.h
===================================================================
--- gcc/collect2.h	(revision 183674)
+++ gcc/collect2.h	(working copy)
@@ -30,7 +30,7 @@  extern void collect_exit (int) ATTRIBUTE
 
 extern int collect_wait (const char *, struct pex_obj *);
 
-extern void dump_file (const char *, FILE *);
+extern void dump_file (const char *, FILE *, int);
 
 extern int file_exists (const char *);
 
@@ -40,6 +40,13 @@  extern const char *c_file_name;
 extern struct obstack temporary_obstack;
 extern char *temporary_firstobj;
 extern bool vflag, debug;
+extern int no_demangle;
+
+#ifdef HAVE_LD_DEMANGLE
+#define DEMANGLE_IN_LD 1
+#else
+#define DEMANGLE_IN_LD 0
+#endif
 
 extern void notice_translated (const char *, ...) ATTRIBUTE_PRINTF_1;
 extern void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
Index: gcc/tlink.c
===================================================================
--- gcc/tlink.c	(revision 183674)
+++ gcc/tlink.c	(working copy)
@@ -766,8 +766,49 @@  scan_linker_output (const char *fname)
 void
 do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED)
 {
-  int exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
+  int demangle_in_ld = DEMANGLE_IN_LD;
+  int map_file = FALSE;
+  int exit;
+  char **ld1_argv = ld_argv;
 
+#ifdef HAVE_LD_DEMANGLE
+  /* If there are repositories, proper processing of them depends on
+     the linker passing back mangled symbols.  So, explicitly tell the
+     linker not to demangle.  Also note whether the user requested a map
+     file, which requires special postprocessing.
+     We can skip this whole business if the user already asked
+     for non-demangled output.  */
+  if (!no_demangle)
+    {
+      int argc = 0;
+      int repo_files_exist = FALSE;
+      while (ld_argv[argc])
+	{
+	  if (*ld_argv[argc] == '-')
+	    {
+	      if (strncmp (ld_argv[argc], "-Map", 4) == 0)
+		map_file = TRUE;
+	    }
+	  else if (!repo_files_exist)
+	    {
+	      const char *p = frob_extension (ld_argv[argc], ".rpo");
+	      if (file_exists (p))
+		repo_files_exist = TRUE;
+	    }
+	  ++argc;
+	}
+      if (repo_files_exist)
+	{
+	  ld1_argv = XNEWVEC (char *, argc + 2);
+	  memcpy (ld1_argv, ld_argv, sizeof (ld_argv[0]) * argc);
+	  ld1_argv[argc] = CONST_CAST (char *, "--no-demangle");
+	  ld1_argv[argc + 1] = NULL;
+	  demangle_in_ld = FALSE;
+	}
+    }
+#endif
+
+  exit = tlink_execute ("ld", ld1_argv, ldout, lderrout);
   tlink_init ();
 
   if (exit)
@@ -781,8 +822,8 @@  do_tlink (char **ld_argv, char **object_
 	  {
 	    if (tlink_verbose >= 3)
 	      {
-		dump_file (ldout, stdout);
-		dump_file (lderrout, stderr);
+		dump_file (ldout, stdout, demangle_in_ld);
+		dump_file (lderrout, stderr, demangle_in_ld);
 	      }
 	    demangle_new_symbols ();
 	    if (! scan_linker_output (ldout)
@@ -792,13 +833,30 @@  do_tlink (char **ld_argv, char **object_
 	      break;
 	    if (tlink_verbose)
 	      fprintf (stderr, _("collect: relinking\n"));
-	    exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
+	    exit = tlink_execute ("ld", ld1_argv, ldout, lderrout);
 	  }
     }
 
-  dump_file (ldout, stdout);
+#ifdef HAVE_LD_DEMANGLE
+  if (!demangle_in_ld)
+    {
+      XDELETEVEC (ld1_argv);
+      /* If the user specified all of demangling, a map file, and repositories,
+	 we must re-link once more with the original options to get the map
+	 file demangled. */
+      if (map_file)
+	{
+	  demangle_in_ld = TRUE;
+	  if (tlink_verbose)
+	    fprintf (stderr, _("collect: relinking\n"));
+	  exit = tlink_execute ("ld", ld_argv, ldout, lderrout);
+	}
+    }
+#endif
+
+  dump_file (ldout, stdout, demangle_in_ld);
   unlink (ldout);
-  dump_file (lderrout, stderr);
+  dump_file (lderrout, stderr, demangle_in_ld);
   unlink (lderrout);
   if (exit)
     {
Index: gcc/testsuite/g++.dg/torture/pr51910.C
===================================================================
--- gcc/testsuite/g++.dg/torture/pr51910.C	(revision 0)
+++ gcc/testsuite/g++.dg/torture/pr51910.C	(revision 0)
@@ -0,0 +1,19 @@ 
+// PR c++/51910 
+// Check that -frepo works in the presence of linker symbol demangling.
+//
+// { dg-options "-frepo -Wl,--demangle" }
+// { dg-require-host-local "" }
+// { dg-skip-if "dkms are not final links" { vxworks_kernel } }
+
+template<typename T>
+struct Foo
+{
+  virtual ~Foo() { }
+};
+
+int main( int, char*[] )
+{
+  Foo<int> test;
+}
+
+// { dg-final { cleanup-repo-files } }