Bug 16934 - gc-sections fails to remove unused C++ member functions
Summary: gc-sections fails to remove unused C++ member functions
Status: RESOLVED INVALID
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.25
: P2 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-05-12 08:07 UTC by curaga
Modified: 2022-07-30 01:58 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Tarball of the testcase. (542 bytes, application/x-gzip)
2014-05-12 08:07 UTC, curaga
Details

Note You need to log in before you can comment on or make changes to this bug.
Description curaga 2014-05-12 08:07:11 UTC
Created attachment 7595 [details]
Tarball of the testcase.

This is an enhancement request. In ld 2.23.1, gc-sections fails to remove some unused C++ class members. This is causing binaries linked with static C++ libs to be megs larger than they could be.

Each function is correctly in a separate section, and is not referenced anywhere in the app.

Attaching a reduced testcase, and also posting the code as comments.
Comment 1 curaga 2014-05-12 08:08:13 UTC
lib.h:

#ifndef FOO_H
#define FOO_H

class interface {
public:
	virtual void foo() = 0;
	virtual void bar() = 0;
};

interface* getclass();

#endif
Comment 2 curaga 2014-05-12 08:08:29 UTC
lib.cpp:

#include <stdio.h>
#include "lib.h"

class myclass: public interface {

public:
	void foo() { puts("foo"); }
	void bar() { puts("bar"); }

};

interface *getclass() {
	return new myclass;
}
Comment 3 curaga 2014-05-12 08:08:43 UTC
app.cpp:

#include "lib.h"
int main() {

	interface *i = getclass();

	i->bar();

	return 0;
}
Comment 4 Nick Clifton 2014-06-17 14:25:15 UTC
Hi Curaga,

  What extraneous code is left in the executable ?

  Does the problem persist with the 2.24 relase or the current mainline development sources ?

Cheers
  Nick
Comment 5 curaga 2014-06-18 08:26:29 UTC
It fails to remove the function foo, which is in its own section _ZN7myclass3fooEv and unused.

It still happens on current git, 2.24.51.20140618 or 6a83deeaa804 (Brown paper bag ...).
Comment 6 Nick Clifton 2014-06-18 16:03:17 UTC
Have you tried enabling link-time optimization in gcc.  Ie compiling with -lfto added to the g++ command lines.  This appears to work for the test case you supplied.

The problem I believe is related to the virtual nature of the functions, which are not invoked directly, but rather via pointers stored in a table.  The linker is not sophisticated enough to be able to determine which entries in a given table are unused, so it cannot delete the unneeded virtual functions.

Cheers
  Nick
Comment 7 curaga 2014-06-19 09:44:29 UTC
That's why this is an enhancement request :)

I'd like to see that sophistication added to the linker. This is needed separately from LTO for various reasons:
- use with older compilers that do not support LTO
- use with projects so big that LTO cannot be used (Firefox, Webkit) because of prohibiting RAM requirements
- use with projects that need fast compilation, but small binaries. LTO comes with a severe compile time hit
- use with projects that are buggy with LTO

It's completely feasible without LTO and would benefit many cases. LTO is problematic in some cases, slow, and RAM-hungry, whereas gc-sections has not failed me once, and is quite fast and light on RAM in comparison.
Comment 8 Alan Modra 2022-07-30 01:58:20 UTC
What you'd need is some way for the linker to recognise that references from vtables should not be followed for the purpose of marking sections against garbage collection, and some way of marking the functions called at their call sites.  The former is easy enough, the latter is impossible.  The linker can't know the function called, by the very nature of virtual functions.