[PATCH] use per function sections + --gc-sections: saves ~5k

Erik Andersen andersen at codepoet.org
Fri Mar 3 10:32:20 PST 2006


On Fri Mar 03, 2006 at 12:47:05PM -0500, Rob Landley wrote:
> On Friday 03 March 2006 1:24 am, Denis Vlasenko wrote:
> > Hi,
> >
> > This patch passes -ffunction-sections -fdata-sections to gcc
> > and --gc-sections to ld. Result:
> >
> > # size busybox.org.tst/busybox busybox.sections.tst/busybox
> >    text    data     bss     dec     hex filename
> >  920143   12268 1047076 1979487  1e345f busybox.org.tst/busybox
> >  915759   10616 1045572 1971947  1e16eb busybox.sections.tst/busybox
> 
> That's highly cool.  What exactly does this do?  (If somebody who understands 
> what this does wants to apply it, I have no objections...)

It tries to place each function into its own ELF section
so the linker can do a better job of pruning dead code.

It should not however be helping, since we should already be
doing that manually, i.e. each function should already be placed
into a separate .o file.  This suggests that rtnl_from_file(),
rtnl_listen(), rtnl_rtrealm_tab(), and rtnl_rttable_tab() are
currently being included unconditionally in libnetlink.c, even
in cases where they are not being used.

Using -ffunction-sections and -fdata-sections to find such
offenders is a good idea.  Unconditionally using them is not such
a great idea, since they only work properly in the newest gcc
revisions, and can lead to lazy bloatish coding.

Something like the following should produce the same effect
without the gcc version dependancy, and has the added advantage
of removing some long standing dead code.

 -Erik

--
Erik B. Andersen             http://codepoet-consulting.com/
--This message was written using 73% post-consumer electrons--


--- networking/libiproute/libnetlink.h	(revision 14436)
+++ networking/libiproute/libnetlink.h	(working copy)
@@ -37,10 +37,6 @@
 
 extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len);
 
-extern int rtnl_listen(struct rtnl_handle *, int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-		       void *jarg);
-extern int rtnl_from_file(FILE *, int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-		       void *jarg);
 
 #endif /* __LIBNETLINK_H__ */
 
--- networking/libiproute/rt_names.c	(revision 14436)
+++ networking/libiproute/rt_names.c	(working copy)
@@ -207,23 +207,6 @@
 			    rtnl_rtrealm_tab, 256);
 }
 
-const char * rtnl_rtrealm_n2a(int id, char *buf, int len)
-{
-	if (id<0 || id>=256) {
-		snprintf(buf, len, "%d", id);
-		return buf;
-	}
-	if (!rtnl_rtrealm_tab[id]) {
-		if (!rtnl_rtrealm_init)
-			rtnl_rtrealm_initialize();
-	}
-	if (rtnl_rtrealm_tab[id])
-		return rtnl_rtrealm_tab[id];
-	snprintf(buf, len, "%d", id);
-	return buf;
-}
-
-
 int rtnl_rtrealm_a2n(uint32_t *id, char *arg)
 {
 	static char *cache = NULL;
@@ -258,70 +241,6 @@
 
 
 
-static char * rtnl_rttable_tab[256] = {
-	"unspec",
-};
-
-static int rtnl_rttable_init;
-
-static void rtnl_rttable_initialize(void)
-{
-	rtnl_rttable_init = 1;
-	rtnl_rttable_tab[255] = "local";
-	rtnl_rttable_tab[254] = "main";
-	rtnl_tab_initialize("/etc/iproute2/rt_tables",
-			    rtnl_rttable_tab, 256);
-}
-
-const char * rtnl_rttable_n2a(int id, char *buf, int len)
-{
-	if (id<0 || id>=256) {
-		snprintf(buf, len, "%d", id);
-		return buf;
-	}
-	if (!rtnl_rttable_tab[id]) {
-		if (!rtnl_rttable_init)
-			rtnl_rttable_initialize();
-	}
-	if (rtnl_rttable_tab[id])
-		return rtnl_rttable_tab[id];
-	snprintf(buf, len, "%d", id);
-	return buf;
-}
-
-int rtnl_rttable_a2n(uint32_t *id, char *arg)
-{
-	static char *cache = NULL;
-	static unsigned long res;
-	char *end;
-	int i;
-
-	if (cache && strcmp(cache, arg) == 0) {
-		*id = res;
-		return 0;
-	}
-
-	if (!rtnl_rttable_init)
-		rtnl_rttable_initialize();
-
-	for (i=0; i<256; i++) {
-		if (rtnl_rttable_tab[i] &&
-		    strcmp(rtnl_rttable_tab[i], arg) == 0) {
-			cache = rtnl_rttable_tab[i];
-			res = i;
-			*id = res;
-			return 0;
-		}
-	}
-
-	i = strtoul(arg, &end, 0);
-	if (!end || end == arg || *end || i > 255)
-		return -1;
-	*id = i;
-	return 0;
-}
-
-
 static char * rtnl_rtdsfield_tab[256] = {
 	"0",
 };
--- networking/libiproute/rt_names.h	(revision 14436)
+++ networking/libiproute/rt_names.h	(working copy)
@@ -5,12 +5,9 @@
 
 extern const char* rtnl_rtprot_n2a(int id, char *buf, int len);
 extern const char* rtnl_rtscope_n2a(int id, char *buf, int len);
-extern const char* rtnl_rttable_n2a(int id, char *buf, int len);
-extern const char* rtnl_rtrealm_n2a(int id, char *buf, int len);
 extern const char* rtnl_dsfield_n2a(int id, char *buf, int len);
 extern int rtnl_rtprot_a2n(uint32_t *id, char *arg);
 extern int rtnl_rtscope_a2n(uint32_t *id, char *arg);
-extern int rtnl_rttable_a2n(uint32_t *id, char *arg);
 extern int rtnl_rtrealm_a2n(uint32_t *id, char *arg);
 extern int rtnl_dsfield_a2n(uint32_t *id, char *arg);
 
--- networking/libiproute/libnetlink.c	(revision 14436)
+++ networking/libiproute/libnetlink.c	(working copy)
@@ -319,134 +319,6 @@
 	}
 }
 
-int rtnl_listen(struct rtnl_handle *rtnl,
-	      int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-	      void *jarg)
-{
-	int status;
-	struct nlmsghdr *h;
-	struct sockaddr_nl nladdr;
-	struct iovec iov;
-	char   buf[8192];
-	struct msghdr msg = {
-		(void*)&nladdr, sizeof(nladdr),
-		&iov,	1,
-		NULL,	0,
-		0
-	};
-
-	memset(&nladdr, 0, sizeof(nladdr));
-	nladdr.nl_family = AF_NETLINK;
-	nladdr.nl_pid = 0;
-	nladdr.nl_groups = 0;
-
-
-	iov.iov_base = buf;
-
-	while (1) {
-		iov.iov_len = sizeof(buf);
-		status = recvmsg(rtnl->fd, &msg, 0);
-
-		if (status < 0) {
-			if (errno == EINTR)
-				continue;
-			bb_perror_msg("OVERRUN");
-			continue;
-		}
-		if (status == 0) {
-			bb_error_msg("EOF on netlink");
-			return -1;
-		}
-		if (msg.msg_namelen != sizeof(nladdr)) {
-			bb_error_msg_and_die("Sender address length == %d", msg.msg_namelen);
-		}
-		for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) {
-			int err;
-			int len = h->nlmsg_len;
-			int l = len - sizeof(*h);
-
-			if (l<0 || len>status) {
-				if (msg.msg_flags & MSG_TRUNC) {
-					bb_error_msg("Truncated message");
-					return -1;
-				}
-				bb_error_msg_and_die("!!!malformed message: len=%d", len);
-			}
-
-			err = handler(&nladdr, h, jarg);
-			if (err < 0) {
-				return err;
-			}
-
-			status -= NLMSG_ALIGN(len);
-			h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len));
-		}
-		if (msg.msg_flags & MSG_TRUNC) {
-			bb_error_msg("Message truncated");
-			continue;
-		}
-		if (status) {
-			bb_error_msg_and_die("!!!Remnant of size %d", status);
-		}
-	}
-}
-
-int rtnl_from_file(FILE *rtnl,
-	      int (*handler)(struct sockaddr_nl *,struct nlmsghdr *n, void *),
-	      void *jarg)
-{
-	int status;
-	struct sockaddr_nl nladdr;
-	char   buf[8192];
-	struct nlmsghdr *h = (void*)buf;
-
-	memset(&nladdr, 0, sizeof(nladdr));
-	nladdr.nl_family = AF_NETLINK;
-	nladdr.nl_pid = 0;
-	nladdr.nl_groups = 0;
-
-	while (1) {
-		int err, len, type;
-		int l;
-
-		status = fread(&buf, 1, sizeof(*h), rtnl);
-
-		if (status < 0) {
-			if (errno == EINTR)
-				continue;
-			bb_perror_msg("rtnl_from_file: fread");
-			return -1;
-		}
-		if (status == 0)
-			return 0;
-
-		len = h->nlmsg_len;
-		type= h->nlmsg_type;
-		l = len - sizeof(*h);
-
-		if (l<0 || len>sizeof(buf)) {
-			bb_error_msg("!!!malformed message: len=%d @%lu",
-				len, ftell(rtnl));
-			return -1;
-		}
-
-		status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl);
-
-		if (status < 0) {
-			bb_perror_msg("rtnl_from_file: fread");
-			return -1;
-		}
-		if (status < l) {
-			bb_error_msg("rtnl-from_file: truncated message");
-			return -1;
-		}
-
-		err = handler(&nladdr, h, jarg);
-		if (err < 0)
-			return err;
-	}
-}
-
 int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data)
 {
 	int len = RTA_LENGTH(4);


More information about the busybox mailing list