diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c8a71dbd53aba46c4af908be6224dc16c0c47426..c1b7a8e2f39ab680763e6c9a462e868597b0b17b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2011-12-01  Nathan Sidwell  <nathan@acm.org>
+
+	PR gcov-profile/51113
+	* coverage.c (build_var): Keep coverage variables static.
+
 2011-12-01  Jakub Jelinek  <jakub@redhat.com>
 
 	PR tree-optimization/51356
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 65ceba227834f4fa5bc0692299b58309d852f08f..23cb2f8cf5591b599e773a4a9b5101876cb91403 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -657,8 +657,7 @@ coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
 }
 
 /* Build a coverage variable of TYPE for function FN_DECL.  If COUNTER
-   >= 0 it is a counter array, otherwise it is the function structure.
-   Propagate appropriate linkage and visibility from the function decl.  */
+   >= 0 it is a counter array, otherwise it is the function structure.  */
 
 static tree
 build_var (tree fn_decl, tree type, int counter)
@@ -675,21 +674,6 @@ build_var (tree fn_decl, tree type, int counter)
   TREE_STATIC (var) = 1;
   TREE_ADDRESSABLE (var) = 1;
   DECL_ALIGN (var) = TYPE_ALIGN (type);
-  DECL_WEAK (var) = DECL_WEAK (fn_decl);
-  TREE_PUBLIC (var)
-    = TREE_PUBLIC (fn_decl) && (counter < 0 || DECL_WEAK (fn_decl));
-  if (DECL_ONE_ONLY (fn_decl))
-    make_decl_one_only (var, DECL_COMDAT_GROUP (fn_decl));
-  
-  if (TREE_PUBLIC (var))
-    {
-      DECL_VISIBILITY (var) = DECL_VISIBILITY (fn_decl);
-      DECL_VISIBILITY_SPECIFIED (var)
-	= DECL_VISIBILITY_SPECIFIED (fn_decl);
-
-      /* Initialize assembler name so we can stream out. */
-      DECL_ASSEMBLER_NAME (var);
-    }
 
   return var;
 }
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b7e73f13e52a3685bf13688a25fddcfadf9f7873..d0548caa2ee8abcbb508c6d8b0efe0b1c5897ceb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,16 @@
+2011-12-01  Nathan Sidwell  <nathan@acm.org>
+
+	PR gcov-profile/51113
+	* lib/gcov.exp (verify-lines): Add support for xfailing.
+	(run-gcov): Likewise.
+	* gcc.misc-tests/gcov-13.c: Xfail weak function.
+	* gcc.misc-tests/gcov-16.c: Remove.
+	* gcc.misc-tests/gcov-17.c: Remove.
+	* g++.dg/gcov-8.C: Remove.
+	* g++.dg/gcov-9.C: Remove.
+	* g++.dg/gcovpart-12b.C: New.
+	* g++.dg/gcov-12.C: New.
+
 2011-12-01  Andrew Pinski  <apinski@cavium.com>
 
 	PR lto/51198
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-12.C b/gcc/testsuite/g++.dg/gcov/gcov-12.C
new file mode 100644
index 0000000000000000000000000000000000000000..c4708e40726b7ce813064c15d9df1d49e24beb15
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/gcov-12.C
@@ -0,0 +1,21 @@
+/* PR 51113 */
+/* { dg-options "-fprofile-arcs -ftest-coverage -fpic" } */
+/* { dg-do run { target native } } */
+/* { dg-additional-sources "gcovpart-12b.C" } */
+
+struct Foo {
+  Foo ()
+  {}  /* count(1) */
+  virtual void Func () /* count(#####) */
+  {}   /* count(#####) */
+};
+
+int main ()
+{
+  Foo b;
+  
+  return 0;  /* count (1) */
+}
+
+/* { dg-final { run-gcov gcov-12.C } } */
+/* { dg-final { run-gcov gcovpart-12b.C { xfail *-*-* } } } */
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-8.C b/gcc/testsuite/g++.dg/gcov/gcov-8.C
deleted file mode 100644
index 272cefc373b4cbf269a63168e7d1ebfdd7a9f90b..0000000000000000000000000000000000000000
--- a/gcc/testsuite/g++.dg/gcov/gcov-8.C
+++ /dev/null
@@ -1,14 +0,0 @@
-/* { dg-options "-fprofile-arcs -fvisibility=hidden" } */
-/* { dg-require-visibility "" } */
-
-struct __attribute__((visibility ("hidden"))) X
-{
-  void Fink ();
-};
-
-void X::Fink ()
-{
-}
-
-/* { dg-final { scan-assembler "\\.hidden\t__gcov___ZN1X4FinkEv" { target { ! *-*-darwin*  } } } } */
-/* { dg-final { scan-assembler "\\.private_extern ___gcov___ZN1X4FinkEv" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-9.C b/gcc/testsuite/g++.dg/gcov/gcov-9.C
deleted file mode 100644
index b9c64d22e561f34ebce1526409eb637b0fbc04c7..0000000000000000000000000000000000000000
--- a/gcc/testsuite/g++.dg/gcov/gcov-9.C
+++ /dev/null
@@ -1,17 +0,0 @@
-/* { dg-options "-fprofile-arcs -fvisibility-inlines-hidden" } */
-/* { dg-require-visibility "" } */
-
-inline void Boo ()
-{
-}
-
-extern "C" void (*Foo ()) ()
-{
-  return Boo;
-}
-
-/* { dg-final { scan-assembler "\\.hidden\t__gcov___Z3Boov" { target { ! *-*-darwin*  } } } } */
-/* { dg-final { scan-assembler "\\.private_extern ___gcov___Z3Boov" { target *-*-darwin* } } } */
-/* { dg-final { scan-assembler "__gcov__Foo:" } } */
-/* { dg-final { scan-assembler-not "\\.hidden\t__gcov__Foo" { target { ! *-*-darwin*  } } } } */
-/* { dg-final { scan-assembler-not "\\.private_extern ___gcov__Foo" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/g++.dg/gcov/gcovpart-12b.C b/gcc/testsuite/g++.dg/gcov/gcovpart-12b.C
new file mode 100644
index 0000000000000000000000000000000000000000..6a1f981f0df57d1643534be969333053840b8fff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/gcovpart-12b.C
@@ -0,0 +1,5 @@
+struct Foo {
+  Foo () {}
+  virtual void Func () /* count(-) { xfail *-*-* } */
+  {}   /* count(-) { xfail *-*-* } */
+};
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-13.c b/gcc/testsuite/gcc.misc-tests/gcov-13.c
index 14be8f9e103432d405645e4c220cee580cfecdb3..fa9680b2544df00531e723fe32182617cb7b3ec5 100644
--- a/gcc/testsuite/gcc.misc-tests/gcov-13.c
+++ b/gcc/testsuite/gcc.misc-tests/gcov-13.c
@@ -7,7 +7,7 @@
 
 int __attribute__ ((weak)) weak ()
 {
-  return 1;  /* count(-) */
+  return 1;  /* count(-) { xfail *-*-* } */
 }
 
 int main ()
@@ -15,5 +15,5 @@ int main ()
   return weak (); /* count(1) */
 }
 
-/* { dg-final { run-gcov { -a gcov-13.c } } } */
+/* { dg-final { run-gcov { -a gcov-13.c } { xfail *-*-* } } } */
 /* { dg-final { run-gcov { -a gcovpart-13b.c } } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-16.c b/gcc/testsuite/gcc.misc-tests/gcov-16.c
deleted file mode 100644
index 478f44a367d5f53c63c1ea53e8147a53e20db3b1..0000000000000000000000000000000000000000
--- a/gcc/testsuite/gcc.misc-tests/gcov-16.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/* Test visibility is copied */
-
-/* { dg-options "-fprofile-arcs -fvisibility=hidden" } */
-/* { dg-require-visibility "" } */
-/* { dg-require-weak "" } */
-
-void Foo ()
-{
-}
-
- /* { dg-final { scan-assembler "\\.hidden\t__gcov__Foo" { target { ! *-*-darwin*  } } } } */
- /* { dg-final { scan-assembler "\\.private_extern ___gcov__Foo" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-17.c b/gcc/testsuite/gcc.misc-tests/gcov-17.c
deleted file mode 100644
index f8ff794215cefbe795707240e732dd6613008aa7..0000000000000000000000000000000000000000
--- a/gcc/testsuite/gcc.misc-tests/gcov-17.c
+++ /dev/null
@@ -1,12 +0,0 @@
-/* Test visibility is copied */
-
-/* { dg-options "-fprofile-arcs" } */
-/* { dg-require-visibility "" } */
-/* { dg-require-weak "" } */
-
-void __attribute__ ((visibility ("hidden"), weak)) Foo ()
-{
-}
-
-/* { dg-final { scan-assembler "\\.hidden\t__gcov__Foo" { target { ! *-*-darwin*  } } } } */
-/* { dg-final { scan-assembler "\\.private_extern ___gcov__Foo" { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/lib/gcov.exp b/gcc/testsuite/lib/gcov.exp
index 1c7484785db1f36532ae521c414088665f341143..081b3ceb14c2be5ec613dcda61bbd53cb5c0c974 100644
--- a/gcc/testsuite/lib/gcov.exp
+++ b/gcc/testsuite/lib/gcov.exp
@@ -39,19 +39,28 @@ proc clean-gcov { testcase } {
 #
 proc verify-lines { testcase file } {
     #send_user "verify-lines\n"
+    global subdir
     set failed 0
     set fd [open $file r]
     while { [gets $fd line] >= 0 } {
         # We want to match both "-" and "#####" as count as well as numbers,
         # since we want to detect lines that shouldn't be marked as covered.
-	if [regexp "^ *(\[^:]*): *(\[0-9\\-#]+):.*count\\((\[0-9\\-#]+)\\)" \
-		"$line" all is n shouldbe] {
+	if [regexp "^ *(\[^:]*): *(\[0-9\\-#]+):.*count\\((\[0-9\\-#]+)\\)(.*)" \
+		"$line" all is n shouldbe rest] {
+	    if [regexp "^ *{(.*)}" $rest all xfailed] {
+		switch [dg-process-target $xfailed] {
+		    "N" { continue }
+		    "F" { setup_xfail "*-*-*" }
+		}
+	    }
 	    if { $is == "" } {
-		fail "$n:no data available for this line"
+		fail "$subdir/$testcase:$n:no data available for this line"
 		incr failed
 	    } elseif { $is != $shouldbe } {
-		fail "$n:is $is:should be $shouldbe"
+		fail "$subdir/$testcase:$n:is $is:should be $shouldbe"
 		incr failed
+	    } else {
+		pass "$subdir/$testcase:$n line count"
 	    }
 	}
     }
@@ -230,32 +239,36 @@ proc run-gcov { args } {
     global GCOV
     global srcdir subdir
 
-    set gcov_args [lindex $args end]
-
+    set gcov_args ""
     set gcov_verify_calls 0
     set gcov_verify_branches 0
-    set gcov_execute_xfail ""
-    set gcov_verify_xfail ""
+    set xfailed 0
 
     foreach a $args {
 	if { $a == "calls" } {
 	  set gcov_verify_calls 1
 	} elseif { $a == "branches" } {
 	  set gcov_verify_branches 1
+	} elseif { $gcov_args == "" } {
+	    set gcov_args $a
+	} else {
+	    switch [dg-process-target $a] {
+		"N" { return }
+		"F" { set xfailed 1 }
+	    }
 	}
     }
 
     # Extract the test name from the arguments.
     set testcase [lindex $gcov_args end]
 
-    if { $gcov_execute_xfail != "" } {
-	eval setup_xfail [split $gcov_execute_xfail]
-    }
-
     verbose "Running $GCOV $testcase" 2
     set testcase [remote_download host $testcase]
     set result [remote_exec host $GCOV $gcov_args]
     if { [lindex $result 0] != 0 } {
+	if { $xfailed } {
+	    setup_xfail "*-*-*"
+	}
 	fail "$subdir/$testcase gcov failed: [lindex $result 1]"
 	clean-gcov $testcase
 	return
@@ -264,16 +277,15 @@ proc run-gcov { args } {
     # Get the gcov output file after making sure it exists.
     set files [glob -nocomplain $testcase.gcov]
     if { $files == "" } {
+	if { $xfailed } {
+	    setup_xfail "*-*-*"
+	}
         fail "$subdir/$testcase gcov failed: $testcase.gcov does not exist"
         clean-gcov $testcase
         return
     }
     remote_upload host $testcase.gcov $testcase.gcov
 
-    if { $gcov_verify_xfail != "" } {
-	eval setup_xfail [split $gcov_verify_xfail]
-    }
-
     # Check that line execution counts are as expected.
     set lfailed [verify-lines $testcase $testcase.gcov]
 
@@ -293,6 +305,9 @@ proc run-gcov { args } {
     # Report whether the gcov test passed or failed.  If there were
     # multiple failures then the message is a summary.
     set tfailed [expr $lfailed + $bfailed + $cfailed]
+    if { $xfailed } {
+	setup_xfail "*-*-*"
+    }
     if { $tfailed > 0 } {
 	fail "$subdir/$testcase gcov: $lfailed failures in line counts, $bfailed in branch percentages, $cfailed in return percentages"
     } else {