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 <san...@codesourcery.com>
Jason Merrill <ja...@redhat.com>
Jakub Jelinek <ja...@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.
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 } }