This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Patch to fix a bug when a kept comdat section is garbage collected.
- From: Sriraman Tallam <tmsriram at google dot com>
- To: binutils at sourceware dot org
- Date: Fri, 22 May 2009 11:17:29 -0700
- Subject: Patch to fix a bug when a kept comdat section is garbage collected.
Hi,
I noticed this bug when --gc-sections is used and the kept
comdat sections get
garbage collected.
How to reproduce :
comd1.cc
---------------
template <class T>
T GetMax (T a, T b)
{
return (a > b)?a:b;
}
int foo();
int bar ()
{
return GetMax <int> (4,5) + foo();
}
int main()
{
return 0;
}
comd2.cc
--------------
template <class T>
T GetMax (T a, T b)
{
return (a > b)?a:b;
}
int foo ()
{
return GetMax <int> (10,11);
}
$ g++ -g -c -ffunction-sections comd1.cc
$ g++ -g -c -ffunction-sections comd2.cc
$g++ -Wl,--gc-sections comd1.o comd2.o
ld: internal error in map_to_kept_section, at ../../src/gold/object.cc:1876
The reason is that a debug_section corresponding to a discarded comdat
section is trying to find
the appropriate kept section. However, the kept section is garbage
collected and it's os = NULL.
Hence, the assertion failure.
Here is a patch to fix the bug along with a test case :
Index: object.cc
===================================================================
RCS file: /cvs/src/src/gold/object.cc,v
retrieving revision 1.90
diff -u -p -u -r1.90 object.cc
--- object.cc 24 Mar 2009 18:42:10 -0000 1.90
+++ object.cc 22 May 2009 18:12:55 -0000
@@ -1873,8 +1873,8 @@ Sized_relobj<size, big_endian>::map_to_k
*found = true;
Output_section* os = kept->object_->output_section(kept->shndx_);
Address offset = kept->object_->get_output_section_offset(kept->shndx_);
- gold_assert(os != NULL && offset != invalid_address);
- return os->address() + offset;
+ if (os != NULL && offset != invalid_address)
+ return os->address() + offset;
}
*found = false;
return 0;
Index: testsuite/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v
retrieving revision 1.88
diff -u -p -u -r1.88 Makefile.am
--- testsuite/Makefile.am 19 May 2009 22:14:17 -0000 1.88
+++ testsuite/Makefile.am 22 May 2009 18:12:55 -0000
@@ -23,6 +23,7 @@ TEST_OBJDUMP = $(top_builddir)/../binuti
TEST_CXXFILT = $(top_builddir)/../binutils/cxxfilt
TEST_STRIP = $(top_builddir)/../binutils/strip-new
TEST_AR = $(top_builddir)/../binutils/ar
+TEST_NM = $(top_builddir)/../binutils/nm-new
if PLUGINS
LIBDL = -ldl
@@ -103,6 +104,18 @@ flagstest_ndebug.o: constructor_test.cc
$(CXXCOMPILE) -O0 -c -o $@ $<
+check_SCRIPTS += gc_comdat_test.sh
+check_DATA += gc_comdat_test.stdout
+gc_comdat_test_1.o: gc_comdat_test_1.cc
+ $(CXXCOMPILE) -O0 -c -g -o $@ $<
+gc_comdat_test_2.o: gc_comdat_test_2.cc
+ $(CXXCOMPILE) -O0 -c -g -o $@ $<
+gc_comdat_test: gc_comdat_test_1.o gc_comdat_test_2.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ --gc-sections gc_comdat_test_1.o gc_comdat_test_2.o
+gc_comdat_test.stdout: gc_comdat_test
+ $(TEST_NM) -C gc_comdat_test > gc_comdat_test.stdout
+
+
check_PROGRAMS += basic_test
check_PROGRAMS += basic_static_test
check_PROGRAMS += basic_pic_test
Index: testsuite/gc_comdat_test.sh
===================================================================
RCS file: testsuite/gc_comdat_test.sh
diff -N testsuite/gc_comdat_test.sh
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gc_comdat_test.sh 22 May 2009 18:12:55 -0000
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+# gc_comdat_test.sh -- test --gc-sections
+
+# Copyright 2009 Free Software Foundation, Inc.
+# Written by Sriraman Tallam <tmsriram@google.com>.
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# The goal of this program is to verify if comdat's and garbage
+# collection work together. Files gc_comdat_test_1.cc and
+# gc_comdat_test_2.cc are used in this test. This program checks
+# if the kept comdat section is garbage collected.
+
+check()
+{
+ if ! grep -q "$2" "$1"
+ then
+ echo "Garbage collection failed to collect :"
+ echo " $2"
+ exit 1
+ fi
+}
+
+check gc_comdat_test.stdout "foo()"
+check gc_comdat_test.stdout "bar()"
+check gc_comdat_test.stdout "int GetMax<int>(int, int)"
Index: testsuite/gc_comdat_test_1.cc
===================================================================
RCS file: testsuite/gc_comdat_test_1.cc
diff -N testsuite/gc_comdat_test_1.cc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gc_comdat_test_1.cc 22 May 2009 18:12:55 -0000
@@ -0,0 +1,42 @@
+// gc_comdat_test_1.cc -- a test case for gold
+
+// Copyright 2009 Free Software Foundation, Inc.
+// Written by Sriraman Tallam <tmsriram@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+// The goal of this program is to verify if comdat's and garbage
+// collection work together. This file is compiled with -g. The
+// comdat kept function for GetMax is garbage.
+
+int foo();
+template <class T>
+T GetMax (T a, T b)
+{
+ return (a > b)?a:b;
+}
+
+int bar ()
+{
+ return GetMax <int> (4,5);
+}
+
+int main()
+{
+ return 0;
+}
Index: testsuite/gc_comdat_test_2.cc
===================================================================
RCS file: testsuite/gc_comdat_test_2.cc
diff -N testsuite/gc_comdat_test_2.cc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gc_comdat_test_2.cc 22 May 2009 18:12:55 -0000
@@ -0,0 +1,35 @@
+// gc_comdat_test_2.cc -- a test case for gold
+
+// Copyright 2009 Free Software Foundation, Inc.
+// Written by Sriraman Tallam <tmsriram@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+// The goal of this program is to verify if comdat's and garbage
+// collection work together. This file is compiled with -g.
+
+template <class T>
+T GetMax (T a, T b)
+{
+ return (a > b)?a:b;
+}
+
+int foo ()
+{
+ return GetMax <int> (10,11);
+}
Changes :
* object.cc (Sized_relobj::map_to_kept_section): Return NULL if the
kept comdat section was garbage collected.
* testsuite/Makefile.am: Add test gc_comdat_test.sh.
* testsuite/Makefile.in: Regenerate.
* testsuite/gc_comdat_test.sh: New file.
* testsuite/gc_comdat_test_1.cc: New file.
* testsuite/gc_comdat_test_2.cc: New file.
Thanks,
-Sriraman Tallam.