svn commit: r276398 - in head/contrib/elftoolchain: elfcopy libdwarf

Ed Maste emaste at FreeBSD.org
Tue Dec 30 03:25:45 UTC 2014


Author: emaste
Date: Tue Dec 30 03:25:42 2014
New Revision: 276398
URL: https://svnweb.freebsd.org/changeset/base/276398

Log:
  Update elftoolchain to upstream rev 3136
  
  This fixes two strip(1) issues found during ports exp-run and adds a
  string hash implementation which significantly speeds up certain
  operations on objects with large numbers of symbols.
  
  This also improves libdwarf handling for stripped objects with
  .eh_frame or .debug_frame (but not other debug) sections.
  
  PR:		196107
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/contrib/elftoolchain/elfcopy/elfcopy.h
  head/contrib/elftoolchain/elfcopy/sections.c
  head/contrib/elftoolchain/elfcopy/segments.c
  head/contrib/elftoolchain/elfcopy/symbols.c
  head/contrib/elftoolchain/libdwarf/libdwarf_abbrev.c
  head/contrib/elftoolchain/libdwarf/libdwarf_info.c
  head/contrib/elftoolchain/libdwarf/libdwarf_init.c
Directory Properties:
  head/contrib/elftoolchain/   (props changed)

Modified: head/contrib/elftoolchain/elfcopy/elfcopy.h
==============================================================================
--- head/contrib/elftoolchain/elfcopy/elfcopy.h	Tue Dec 30 03:19:46 2014	(r276397)
+++ head/contrib/elftoolchain/elfcopy/elfcopy.h	Tue Dec 30 03:25:42 2014	(r276398)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: elfcopy.h 2970 2013-12-01 15:22:12Z kaiwang27 $
+ * $Id: elfcopy.h 3134 2014-12-23 10:43:59Z kaiwang27 $
  */
 
 #include <sys/queue.h>
@@ -115,6 +115,7 @@ struct segment;
 /* Internal data structure for sections. */
 struct section {
 	struct segment	*seg;	/* containing segment */
+	struct segment	*seg_tls; /* tls segment */
 	const char	*name;	/* section name */
 	char		*newname; /* new section name */
 	Elf_Scn		*is;	/* input scn */

Modified: head/contrib/elftoolchain/elfcopy/sections.c
==============================================================================
--- head/contrib/elftoolchain/elfcopy/sections.c	Tue Dec 30 03:19:46 2014	(r276397)
+++ head/contrib/elftoolchain/elfcopy/sections.c	Tue Dec 30 03:25:42 2014	(r276398)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2007-2011 Kai Wang
+ * Copyright (c) 2007-2011,2014 Kai Wang
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,7 +35,7 @@
 
 #include "elfcopy.h"
 
-ELFTC_VCSID("$Id: sections.c 3126 2014-12-21 08:03:31Z kaiwang27 $");
+ELFTC_VCSID("$Id: sections.c 3134 2014-12-23 10:43:59Z kaiwang27 $");
 
 static void	add_gnu_debuglink(struct elfcopy *ecp);
 static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc);
@@ -485,7 +485,10 @@ insert_shtab(struct elfcopy *ecp, int ta
 	if ((shtab = calloc(1, sizeof(*shtab))) == NULL)
 		errx(EXIT_FAILURE, "calloc failed");
 	if (!tail) {
-		/* shoff of input object is used as a hint. */
+		/*
+		 * "shoff" of input object is used as a hint for section
+		 * resync later.
+		 */
 		if (gelf_getehdr(ecp->ein, &ieh) == NULL)
 			errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
 			    elf_errmsg(-1));
@@ -764,6 +767,15 @@ resync_sections(struct elfcopy *ecp)
 			first = 0;
 		}
 
+		/*
+		 * Ignore TLS sections with load address 0 and without
+		 * content. We don't need to adjust their file offset or
+		 * VMA, only the size matters.
+		 */
+		if (s->seg_tls != NULL && s->type == SHT_NOBITS &&
+		    s->off == 0)
+			continue;
+
 		/* Align section offset. */
 		if (off <= s->off) {
 			if (!s->loadable)
@@ -1050,6 +1062,17 @@ copy_data(struct section *s)
 		od->d_size	= id->d_size;
 		od->d_version	= id->d_version;
 	}
+
+	/*
+	 * Alignment Fixup. libelf does not allow the alignment for
+	 * Elf_Data descriptor to be set to 0. In this case we workaround
+	 * it by setting the alignment to 1.
+	 *
+	 * According to the ELF ABI, alignment 0 and 1 has the same
+	 * meaning: the section has no alignment constraints.
+	 */
+	if (od->d_align == 0)
+		od->d_align = 1;
 }
 
 struct section *

Modified: head/contrib/elftoolchain/elfcopy/segments.c
==============================================================================
--- head/contrib/elftoolchain/elfcopy/segments.c	Tue Dec 30 03:19:46 2014	(r276397)
+++ head/contrib/elftoolchain/elfcopy/segments.c	Tue Dec 30 03:25:42 2014	(r276398)
@@ -35,7 +35,7 @@
 
 #include "elfcopy.h"
 
-ELFTC_VCSID("$Id: segments.c 3113 2014-12-20 08:33:29Z kaiwang27 $");
+ELFTC_VCSID("$Id: segments.c 3134 2014-12-23 10:43:59Z kaiwang27 $");
 
 static void	insert_to_inseg_list(struct segment *seg, struct section *sec);
 
@@ -86,6 +86,8 @@ add_to_inseg_list(struct elfcopy *ecp, s
 		insert_to_inseg_list(seg, s);
 		if (seg->type == PT_LOAD)
 			s->seg = seg;
+		else if (seg->type == PT_TLS)
+			s->seg_tls = seg;
 		s->lma = seg->addr + (s->off - seg->off);
 		loadable = 1;
 	}

Modified: head/contrib/elftoolchain/elfcopy/symbols.c
==============================================================================
--- head/contrib/elftoolchain/elfcopy/symbols.c	Tue Dec 30 03:19:46 2014	(r276397)
+++ head/contrib/elftoolchain/elfcopy/symbols.c	Tue Dec 30 03:25:42 2014	(r276398)
@@ -34,7 +34,7 @@
 
 #include "elfcopy.h"
 
-ELFTC_VCSID("$Id: symbols.c 3019 2014-04-17 14:53:40Z jkoshy $");
+ELFTC_VCSID("$Id: symbols.c 3135 2014-12-24 08:22:43Z kaiwang27 $");
 
 /* Symbol table buffer structure. */
 struct symbuf {
@@ -46,12 +46,25 @@ struct symbuf {
 	size_t gcap, lcap; 	/* buffer capacities. */
 };
 
+struct sthash {
+	LIST_ENTRY(sthash) sh_next;
+	size_t sh_off;
+};
+typedef LIST_HEAD(,sthash) hash_head;
+#define STHASHSIZE 65536
+
+struct strimpl {
+	char *buf;		/* string table */
+	size_t sz;		/* entries */
+	size_t cap;		/* buffer capacity */
+	hash_head hash[STHASHSIZE];
+};
+
+
 /* String table buffer structure. */
 struct strbuf {
-	char *l;		/* local symbol string table */
-	char *g;		/* global symbol string table */
-	size_t lsz, gsz;	/* size of each kind */
-	size_t gcap, lcap; 	/* buffer capacities. */
+	struct strimpl l;	/* local symbols */
+	struct strimpl g;	/* global symbols */
 };
 
 static int	is_debug_symbol(unsigned char st_info);
@@ -62,10 +75,12 @@ static int	is_needed_symbol(struct elfco
 static int	is_remove_symbol(struct elfcopy *ecp, size_t sc, int i,
 		    GElf_Sym *s, const char *name);
 static int	is_weak_symbol(unsigned char st_info);
-static int	lookup_exact_string(const char *buf, size_t sz, const char *s);
+static int	lookup_exact_string(hash_head *hash, const char *buf,
+		    const char *s);
 static int	generate_symbols(struct elfcopy *ecp);
 static void	mark_symbols(struct elfcopy *ecp, size_t sc);
 static int	match_wildcard(const char *name, const char *pattern);
+uint32_t	str_hash(const char *s);
 
 /* Convenient bit vector operation macros. */
 #define BIT_SET(v, n) (v[(n)>>3] |= 1U << ((n) & 7))
@@ -316,10 +331,10 @@ generate_symbols(struct elfcopy *ecp)
 	if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL)
 		err(EXIT_FAILURE, "calloc failed");
 	sy_buf->gcap = sy_buf->lcap = 64;
-	st_buf->gcap = 256;
-	st_buf->lcap = 64;
-	st_buf->lsz = 1;	/* '\0' at start. */
-	st_buf->gsz = 0;
+	st_buf->g.cap = 256;
+	st_buf->l.cap = 64;
+	st_buf->l.sz = 1;	/* '\0' at start. */
+	st_buf->g.sz = 0;
 
 	ecp->symtab->sz = 0;
 	ecp->strtab->sz = 0;
@@ -541,10 +556,10 @@ generate_symbols(struct elfcopy *ecp)
 			/* Update st_name. */
 			if (ec == ELFCLASS32)
 				sy_buf->g32[ecp->symndx[i]].st_name +=
-				    st_buf->lsz;
+				    st_buf->l.sz;
 			else
 				sy_buf->g64[ecp->symndx[i]].st_name +=
-				    st_buf->lsz;
+				    st_buf->l.sz;
 
 			/* Update index map. */
 			ecp->symndx[i] += sy_buf->nls;
@@ -633,6 +648,8 @@ free_symtab(struct elfcopy *ecp)
 {
 	struct symbuf	*sy_buf;
 	struct strbuf	*st_buf;
+	struct sthash	*sh, *shtmp;
+	int i;
 
 	if (ecp->symtab != NULL && ecp->symtab->buf != NULL) {
 		sy_buf = ecp->symtab->buf;
@@ -648,10 +665,22 @@ free_symtab(struct elfcopy *ecp)
 
 	if (ecp->strtab != NULL && ecp->strtab->buf != NULL) {
 		st_buf = ecp->strtab->buf;
-		if (st_buf->l != NULL)
-			free(st_buf->l);
-		if (st_buf->g != NULL)
-			free(st_buf->g);
+		if (st_buf->l.buf != NULL)
+			free(st_buf->l.buf);
+		if (st_buf->g.buf != NULL)
+			free(st_buf->g.buf);
+		for (i = 0; i < STHASHSIZE; i++) {
+			LIST_FOREACH_SAFE(sh, &st_buf->l.hash[i], sh_next,
+			    shtmp) {
+				LIST_REMOVE(sh, sh_next);
+				free(sh);
+			}
+			LIST_FOREACH_SAFE(sh, &st_buf->g.hash[i], sh_next,
+			    shtmp) {
+				LIST_REMOVE(sh, sh_next);
+				free(sh);
+			}
+		}
 	}
 }
 
@@ -689,10 +718,10 @@ create_external_symtab(struct elfcopy *e
 	if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL)
 		err(EXIT_FAILURE, "calloc failed");
 	sy_buf->gcap = sy_buf->lcap = 64;
-	st_buf->gcap = 256;
-	st_buf->lcap = 64;
-	st_buf->lsz = 1;	/* '\0' at start. */
-	st_buf->gsz = 0;
+	st_buf->g.cap = 256;
+	st_buf->l.cap = 64;
+	st_buf->l.sz = 1;	/* '\0' at start. */
+	st_buf->g.sz = 0;
 
 	ecp->symtab->sz = 0;
 	ecp->strtab->sz = 0;
@@ -729,6 +758,8 @@ add_to_symtab(struct elfcopy *ecp, const
 {
 	struct symbuf *sy_buf;
 	struct strbuf *st_buf;
+	struct sthash *sh;
+	uint32_t hash;
 	int pos;
 
 	/*
@@ -761,32 +792,39 @@ add_to_symtab(struct elfcopy *ecp, const
 	else								\
 		sy_buf->B##SZ[sy_buf->n##B##s].st_shndx	=		\
 			ecp->secndx[st_shndx];				\
-	if (st_buf->B == NULL) {					\
-		st_buf->B = calloc(st_buf->B##cap, sizeof(*st_buf->B));	\
-		if (st_buf->B == NULL)					\
+	if (st_buf->B.buf == NULL) {					\
+		st_buf->B.buf = calloc(st_buf->B.cap,			\
+		    sizeof(*st_buf->B.buf));				\
+		if (st_buf->B.buf == NULL)				\
 			err(EXIT_FAILURE, "malloc failed");		\
 	}								\
 	if (name != NULL && *name != '\0') {				\
-		pos = lookup_exact_string(st_buf->B,			\
-		    st_buf->B##sz, name);				\
+		pos = lookup_exact_string(st_buf->B.hash, st_buf->B.buf,\
+		    name);						\
 		if (pos != -1)						\
 			sy_buf->B##SZ[sy_buf->n##B##s].st_name = pos;	\
 		else {							\
 			sy_buf->B##SZ[sy_buf->n##B##s].st_name =	\
-			    st_buf->B##sz;				\
-			while (st_buf->B##sz + strlen(name) >=		\
-			    st_buf->B##cap - 1) {			\
-				st_buf->B##cap *= 2;			\
-				st_buf->B = realloc(st_buf->B,		\
-				    st_buf->B##cap);			\
-				if (st_buf->B == NULL)			\
+			    st_buf->B.sz;				\
+			while (st_buf->B.sz + strlen(name) >=		\
+			    st_buf->B.cap - 1) {			\
+				st_buf->B.cap *= 2;			\
+				st_buf->B.buf = realloc(st_buf->B.buf,	\
+				    st_buf->B.cap);			\
+				if (st_buf->B.buf == NULL)		\
 					err(EXIT_FAILURE,		\
 					    "realloc failed");		\
 			}						\
-			strncpy(&st_buf->B[st_buf->B##sz], name,	\
+			if ((sh = malloc(sizeof(*sh))) == NULL)		\
+				err(EXIT_FAILURE, "malloc failed");	\
+			sh->sh_off = st_buf->B.sz;			\
+			hash = str_hash(name);				\
+			LIST_INSERT_HEAD(&st_buf->B.hash[hash], sh,	\
+			    sh_next);					\
+			strncpy(&st_buf->B.buf[st_buf->B.sz], name,	\
 			    strlen(name));				\
-			st_buf->B[st_buf->B##sz + strlen(name)] = '\0';	\
-			st_buf->B##sz += strlen(name) + 1;		\
+			st_buf->B.buf[st_buf->B.sz + strlen(name)] = '\0'; \
+			st_buf->B.sz += strlen(name) + 1;		\
 		}							\
 	} else								\
 		sy_buf->B##SZ[sy_buf->n##B##s].st_name = 0;		\
@@ -811,7 +849,7 @@ add_to_symtab(struct elfcopy *ecp, const
 	/* Update section size. */
 	ecp->symtab->sz = (sy_buf->nls + sy_buf->ngs) *
 	    (ecp->oec == ELFCLASS32 ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym));
-	ecp->strtab->sz = st_buf->lsz + st_buf->gsz;
+	ecp->strtab->sz = st_buf->l.sz + st_buf->g.sz;
 
 #undef	_ADDSYM
 }
@@ -831,9 +869,9 @@ finalize_external_symtab(struct elfcopy 
 	st_buf = ecp->strtab->buf;
 	for (i = 0; (size_t) i < sy_buf->ngs; i++) {
 		if (ecp->oec == ELFCLASS32)
-			sy_buf->g32[i].st_name += st_buf->lsz;
+			sy_buf->g32[i].st_name += st_buf->l.sz;
 		else
-			sy_buf->g64[i].st_name += st_buf->lsz;
+			sy_buf->g64[i].st_name += st_buf->l.sz;
 	}
 }
 
@@ -920,19 +958,19 @@ create_symtab_data(struct elfcopy *ecp)
 		    elf_errmsg(-1));
 	lstdata->d_align	= 1;
 	lstdata->d_off		= 0;
-	lstdata->d_buf		= st_buf->l;
-	lstdata->d_size		= st_buf->lsz;
+	lstdata->d_buf		= st_buf->l.buf;
+	lstdata->d_size		= st_buf->l.sz;
 	lstdata->d_type		= ELF_T_BYTE;
 	lstdata->d_version	= EV_CURRENT;
 
-	if (st_buf->gsz > 0) {
+	if (st_buf->g.sz > 0) {
 		if ((gstdata = elf_newdata(st->os)) == NULL)
 			errx(EXIT_FAILURE, "elf_newdata() failed: %s.",
 			    elf_errmsg(-1));
 		gstdata->d_align	= 1;
 		gstdata->d_off		= lstdata->d_size;
-		gstdata->d_buf		= st_buf->g;
-		gstdata->d_size		= st_buf->gsz;
+		gstdata->d_buf		= st_buf->g.buf;
+		gstdata->d_size		= st_buf->g.sz;
 		gstdata->d_type		= ELF_T_BYTE;
 		gstdata->d_version	= EV_CURRENT;
 	}
@@ -1022,18 +1060,25 @@ lookup_symop_list(struct elfcopy *ecp, c
 }
 
 static int
-lookup_exact_string(const char *buf, size_t sz, const char *s)
+lookup_exact_string(hash_head *buckets, const char *buf, const char *s)
 {
-	const char	*b;
-	size_t		 slen;
-
-	slen = strlen(s);
-	for (b = buf; b < buf + sz; b += strlen(b) + 1) {
-		if (strlen(b) != slen)
-			continue;
-		if (!strcmp(b, s))
-			return (b - buf);
-	}
+	struct sthash	*sh;
+	uint32_t	 hash;
 
+	hash = str_hash(s);
+	LIST_FOREACH(sh, &buckets[hash], sh_next)
+		if (strcmp(buf + sh->sh_off, s) == 0)
+			return sh->sh_off;
 	return (-1);
 }
+
+uint32_t
+str_hash(const char *s)
+{
+	uint32_t hash;
+
+	for (hash = 2166136261; *s; s++)
+		hash = (hash ^ *s) * 16777619;
+
+	return (hash & (STHASHSIZE - 1));
+}

Modified: head/contrib/elftoolchain/libdwarf/libdwarf_abbrev.c
==============================================================================
--- head/contrib/elftoolchain/libdwarf/libdwarf_abbrev.c	Tue Dec 30 03:19:46 2014	(r276397)
+++ head/contrib/elftoolchain/libdwarf/libdwarf_abbrev.c	Tue Dec 30 03:25:42 2014	(r276398)
@@ -27,7 +27,7 @@
 
 #include "_libdwarf.h"
 
-ELFTC_VCSID("$Id: libdwarf_abbrev.c 2070 2011-10-27 03:05:32Z jkoshy $");
+ELFTC_VCSID("$Id: libdwarf_abbrev.c 3136 2014-12-24 16:04:38Z kaiwang27 $");
 
 int
 _dwarf_abbrev_add(Dwarf_CU cu, uint64_t entry, uint64_t tag, uint8_t children,
@@ -180,7 +180,9 @@ _dwarf_abbrev_find(Dwarf_CU cu, uint64_t
 
 	/* Load and search the abbrev table. */
 	ds = _dwarf_find_section(cu->cu_dbg, ".debug_abbrev");
-	assert(ds != NULL);
+	if (ds == NULL)
+		return (DW_DLE_NO_ENTRY);
+
 	offset = cu->cu_abbrev_offset_cur;
 	while (offset < ds->ds_size) {
 		ret = _dwarf_abbrev_parse(cu->cu_dbg, cu, &offset, &ab, error);

Modified: head/contrib/elftoolchain/libdwarf/libdwarf_info.c
==============================================================================
--- head/contrib/elftoolchain/libdwarf/libdwarf_info.c	Tue Dec 30 03:19:46 2014	(r276397)
+++ head/contrib/elftoolchain/libdwarf/libdwarf_info.c	Tue Dec 30 03:25:42 2014	(r276398)
@@ -27,7 +27,7 @@
 
 #include "_libdwarf.h"
 
-ELFTC_VCSID("$Id: libdwarf_info.c 3041 2014-05-18 15:11:03Z kaiwang27 $");
+ELFTC_VCSID("$Id: libdwarf_info.c 3136 2014-12-24 16:04:38Z kaiwang27 $");
 
 int
 _dwarf_info_first_cu(Dwarf_Debug dbg, Dwarf_Error *error)
@@ -153,7 +153,8 @@ _dwarf_info_load(Dwarf_Debug dbg, Dwarf_
 			return (ret);
 		offset = dbg->dbg_info_off;
 		ds = dbg->dbg_info_sec;
-		assert(ds != NULL);
+		if (ds == NULL)
+			return (DW_DLE_NO_ENTRY);
 	} else {
 		if (dbg->dbg_types_loaded)
 			return (ret);

Modified: head/contrib/elftoolchain/libdwarf/libdwarf_init.c
==============================================================================
--- head/contrib/elftoolchain/libdwarf/libdwarf_init.c	Tue Dec 30 03:19:46 2014	(r276397)
+++ head/contrib/elftoolchain/libdwarf/libdwarf_init.c	Tue Dec 30 03:25:42 2014	(r276398)
@@ -26,7 +26,7 @@
 
 #include "_libdwarf.h"
 
-ELFTC_VCSID("$Id: libdwarf_init.c 3061 2014-06-02 00:42:41Z kaiwang27 $");
+ELFTC_VCSID("$Id: libdwarf_init.c 3136 2014-12-24 16:04:38Z kaiwang27 $");
 
 static int
 _dwarf_consumer_init(Dwarf_Debug dbg, Dwarf_Error *error)
@@ -93,12 +93,7 @@ _dwarf_consumer_init(Dwarf_Debug dbg, Dw
 	}
 	dbg->dbg_section[cnt].ds_name = NULL;
 
-	if (_dwarf_find_section(dbg, ".debug_abbrev") == NULL ||
-	    ((dbg->dbg_info_sec = _dwarf_find_section(dbg, ".debug_info")) ==
-	     NULL)) {
-		DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_INFO_NULL);
-		return (DW_DLE_DEBUG_INFO_NULL);
-	}
+	dbg->dbg_info_sec = _dwarf_find_section(dbg, ".debug_info");
 
 	/* Try to find the optional DWARF4 .debug_types section. */
 	dbg->dbg_types_sec = _dwarf_find_next_types_section(dbg, NULL);


More information about the svn-src-head mailing list