This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[RFA:] New test for bug in --gc-sections: selective6
- To: binutils at sources dot redhat dot com
- Subject: [RFA:] New test for bug in --gc-sections: selective6
- From: Hans-Peter Nilsson <hp at bitrange dot com>
- Date: Sun, 24 Sep 2000 16:44:57 -0400 (EDT)
I'm trying to prepare a presentation, where a paragraph mentions the
benefits of --gc-sections et al. (Clouded by the fact that it only works
with -static, bummer...)
I wrote some example code to show, where it seems I catch myself lying
about what --gc-sections really does, when used together with the
corresponding GCC option, -fvtable-gc.
Here's a test, selective6, based on selective5 (4.cc), in which functions
to-be-dropped cause a .vtable_entry mark to be emitted, but where it sem
that mark is not in turn garbage-collected, as I believe it should: B::foo
is there, as well as drop1 and drop2 for some reason, perhaps another bug.
Right now I don't know whether it is fixable or if there's a built-in
limitation. I hope to give it a try.
The test fails with assembly output from reasonably-current gcc CVS
i686-pc-linux-gnulibc1 20000923 (and much earlier too), but works for the
other test-cases in selective.exp, and the assembly code looks right,
modulo an unrelated but harmless extra "*" from label mishandling of
'__asm__ ("_start")'. BTW; that's a bad assumption about the start-label
for a target. Right now I'm not looking into fixing it, though.
Ok to commit?
2000-09-24 Hans-Peter Nilsson <hp@bitrange.com>
* ld-selective/5.cc: New test.
* ld-selective/selective.exp: Run it as xfailed.
Index: selective.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-selective/selective.exp,v
retrieving revision 1.7
diff -p -c -r1.7 selective.exp
*** selective.exp 2000/09/05 04:07:46 1.7
--- selective.exp 2000/09/24 19:48:47
*************** set test2 "selective2"
*** 32,37 ****
--- 32,38 ----
set test3 "selective3"
set test4 "selective4"
set test5 "selective5"
+ set test6 "selective6"
set cflags "-w -O2 -ffunction-sections -fdata-sections"
set cxxflags "-fvtable-gc -fno-exceptions -fno-rtti"
*************** if { [which $CXX] == 0 } {
*** 43,48 ****
--- 44,50 ----
untested $test3
untested $test4
untested $test5
+ untested $test6
return
}
*************** if ![ld_simple_link $ld tmpdir/4.x "$ldf
*** 191,193 ****
--- 193,242 ----
}
}
}
+
+ if { ![ld_compile "$CC $cflags $cxxflags" $srcdir/$subdir/5.cc tmpdir/5.o]} {
+ unresolved $test6
+ return
+ }
+
+ # Exposes a bug, currently. FIXME: Fix it.
+ # FIXME: Break out the nesting to a function that takes two lists, one
+ # with expected present symbols, one with expected absent symbols, and
+ # iterates over nm output. Use that function in all tests here.
+
+ setup_xfail "*-*-*"
+
+ if ![ld_simple_link $ld tmpdir/5.x "$ldflags tmpdir/5.o"] {
+ fail $test6
+ } else {
+ if ![ld_nm $nm tmpdir/5.x] {
+ unresolved $test6
+ } else {
+ if {[info exists nm_output(foo__1B)]} {
+ send_log "foo__1B == $nm_output(foo__1B)\n"
+ verbose "foo__1B == $nm_output(foo__1B)"
+ fail $test6
+ } else {
+ if {[info exists nm_output(foo__1A)]} {
+ send_log "foo__1A == $nm_output(foo__1A)\n"
+ verbose "foo__1A == $nm_output(foo__1A)"
+ fail $test6
+ } else {
+ if {[info exists nm_output(dropme1__Fv)]} {
+ send_log "dropme1__Fv == $nm_output(dropme1__Fv)\n"
+ verbose "dropme1__Fv == $nm_output(dropme1__Fv)"
+ fail $test6
+ } else {
+ if {[info exists nm_output(dropme2__Fv)]} {
+ send_log "dropme2__Fv == $nm_output(dropme2__Fv)\n"
+ verbose "dropme2__Fv == $nm_output(dropme2__Fv)"
+ fail $test6
+ } else {
+ pass $test6
+ }
+ }
+ }
+ }
+ }
+ }
+
*** /dev/null Tue Jan 1 05:00:00 1980
--- 5.cc Sun Sep 24 21:02:51 2000
***************
*** 0 ****
--- 1,32 ----
+ struct A
+ {
+ virtual void foo();
+ virtual void bar();
+ };
+
+ void A::foo() { } // loose
+ void A::bar() { } // keep
+
+ struct B : public A
+ {
+ virtual void foo();
+ };
+
+ void B::foo() { } // loose
+
+ void _start() __asm__("_start"); // keep
+
+ A a; // keep
+ B b;
+ A *getme() { return &a; } // keep
+
+ extern B* dropme2();
+ void dropme1() { dropme2()->foo(); } // loose
+ B *dropme2() { return &b; } // loose
+
+ void _start()
+ {
+ getme()->bar();
+ }
+
+ extern "C" void __main() { }
brgds, H-P