diff options
author | Ed Maste <emaste@FreeBSD.org> | 2014-12-30 01:27:18 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2014-12-30 01:27:18 +0000 |
commit | 42bfa111d731278ff40f9ce45298e65a373c2064 (patch) | |
tree | 93decb044b3639075e37c0f46bef0c1b6a0529f8 | |
parent | 5eccfb5cf5403e9e564066e0a75d80534b49e91d (diff) |
Import elftoolchain rev 3136vendor/elftoolchain/elftoolchain-r3136
From svn.code.sf.net/p/elftoolchain/code/trunk
Notes
Notes:
svn path=/vendor/elftoolchain/dist/; revision=276387
svn path=/vendor/elftoolchain/elftoolchain-r3136/; revision=276388; tag=vendor/elftoolchain/elftoolchain-r3136
-rw-r--r-- | elfcopy/elfcopy.h | 3 | ||||
-rw-r--r-- | elfcopy/sections.c | 29 | ||||
-rw-r--r-- | elfcopy/segments.c | 4 | ||||
-rw-r--r-- | elfcopy/symbols.c | 153 | ||||
-rw-r--r-- | libdwarf/libdwarf_abbrev.c | 6 | ||||
-rw-r--r-- | libdwarf/libdwarf_info.c | 5 | ||||
-rw-r--r-- | libdwarf/libdwarf_init.c | 9 |
7 files changed, 139 insertions, 70 deletions
diff --git a/elfcopy/elfcopy.h b/elfcopy/elfcopy.h index 609e2916f527..7b3a9b1af9b4 100644 --- a/elfcopy/elfcopy.h +++ b/elfcopy/elfcopy.h @@ -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 */ diff --git a/elfcopy/sections.c b/elfcopy/sections.c index c503666c8948..6c733f8a0f81 100644 --- a/elfcopy/sections.c +++ b/elfcopy/sections.c @@ -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 tail) 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 * diff --git a/elfcopy/segments.c b/elfcopy/segments.c index e48ad127bfd0..1cdf4664ebec 100644 --- a/elfcopy/segments.c +++ b/elfcopy/segments.c @@ -34,7 +34,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); @@ -85,6 +85,8 @@ add_to_inseg_list(struct elfcopy *ecp, struct section *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; } diff --git a/elfcopy/symbols.c b/elfcopy/symbols.c index 573a18f25e79..7fb6ccba7dd8 100644 --- a/elfcopy/symbols.c +++ b/elfcopy/symbols.c @@ -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 elfcopy *ecp, int i, GElf_Sym *s); 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 *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; @@ -729,6 +758,8 @@ add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value, { 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 char *name, uint64_t st_value, 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 char *name, uint64_t st_value, /* 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 *ecp) 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, const char *name, unsigned int op) } 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)); +} diff --git a/libdwarf/libdwarf_abbrev.c b/libdwarf/libdwarf_abbrev.c index f4a395df0360..abcc2fda9580 100644 --- a/libdwarf/libdwarf_abbrev.c +++ b/libdwarf/libdwarf_abbrev.c @@ -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 entry, Dwarf_Abbrev *abp, /* 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); diff --git a/libdwarf/libdwarf_info.c b/libdwarf/libdwarf_info.c index 261bee6d933e..74765930aaed 100644 --- a/libdwarf/libdwarf_info.c +++ b/libdwarf/libdwarf_info.c @@ -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_Bool load_all, Dwarf_Bool is_info, 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); diff --git a/libdwarf/libdwarf_init.c b/libdwarf/libdwarf_init.c index 8e3fbbe5db36..b85c87c59af0 100644 --- a/libdwarf/libdwarf_init.c +++ b/libdwarf/libdwarf_init.c @@ -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, Dwarf_Error *error) } 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); |