diff --git a/contrib/elftoolchain/elfcopy/ascii.c b/contrib/elftoolchain/elfcopy/ascii.c index 4ba05c427d9e..71217aa197d5 100644 --- a/contrib/elftoolchain/elfcopy/ascii.c +++ b/contrib/elftoolchain/elfcopy/ascii.c @@ -378,9 +378,6 @@ create_elf_from_srec(struct elfcopy *ecp, int ifd) errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", elf_errmsg(-1)); - /* Generate section name string table (.shstrtab). */ - set_shstrtab(ecp); - /* Update sh_name pointer for each section header entry. */ update_shdr(ecp, 0); @@ -605,9 +602,6 @@ create_elf_from_ihex(struct elfcopy *ecp, int ifd) errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", elf_errmsg(-1)); - /* Generate section name string table (.shstrtab). */ - set_shstrtab(ecp); - /* Update sh_name pointer for each section header entry. */ update_shdr(ecp, 0); diff --git a/contrib/elftoolchain/elfcopy/binary.c b/contrib/elftoolchain/elfcopy/binary.c index f2119e48fa75..64a851d96b05 100644 --- a/contrib/elftoolchain/elfcopy/binary.c +++ b/contrib/elftoolchain/elfcopy/binary.c @@ -250,11 +250,8 @@ create_elf_from_binary(struct elfcopy *ecp, int ifd, const char *ifn) errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", elf_errmsg(-1)); - /* Generate section name string table (.shstrtab). */ - ecp->flags |= SYMTAB_EXIST; - set_shstrtab(ecp); - /* Update sh_name pointer for each section header entry. */ + ecp->flags |= SYMTAB_EXIST; update_shdr(ecp, 0); /* Properly set sh_link field of .symtab section. */ diff --git a/contrib/elftoolchain/elfcopy/elfcopy.h b/contrib/elftoolchain/elfcopy/elfcopy.h index a6578113fe55..07905e7fde85 100644 --- a/contrib/elftoolchain/elfcopy/elfcopy.h +++ b/contrib/elftoolchain/elfcopy/elfcopy.h @@ -111,6 +111,7 @@ struct sec_add { }; struct segment; +TAILQ_HEAD(sectionlist, section); /* Internal data structure for sections. */ struct section { @@ -135,6 +136,8 @@ struct section { int pseudo; int nocopy; + Elftc_String_Table *strtab; + TAILQ_ENTRY(section) sec_list; /* next section */ }; diff --git a/contrib/elftoolchain/elfcopy/main.c b/contrib/elftoolchain/elfcopy/main.c index be6f2b760b1b..db6630a45aa6 100644 --- a/contrib/elftoolchain/elfcopy/main.c +++ b/contrib/elftoolchain/elfcopy/main.c @@ -388,9 +388,6 @@ create_elf(struct elfcopy *ecp) */ copy_content(ecp); - /* Generate section name string table (.shstrtab). */ - set_shstrtab(ecp); - /* * Second processing of output sections: Update section headers. * At this stage we set name string index, update st_link and st_info @@ -500,6 +497,8 @@ free_elf(struct elfcopy *ecp) } } + elftc_string_table_destroy(ecp->shstrtab->strtab); + ecp->symtab = NULL; ecp->strtab = NULL; ecp->shstrtab = NULL; @@ -1565,7 +1564,6 @@ main(int argc, char **argv) ecp = calloc(1, sizeof(*ecp)); if (ecp == NULL) err(EXIT_FAILURE, "calloc failed"); - memset(ecp, 0, sizeof(*ecp)); ecp->itf = ecp->otf = ETF_ELF; ecp->iec = ecp->oec = ELFCLASSNONE; diff --git a/contrib/elftoolchain/elfcopy/sections.c b/contrib/elftoolchain/elfcopy/sections.c index f8134f944615..7892c90416c4 100644 --- a/contrib/elftoolchain/elfcopy/sections.c +++ b/contrib/elftoolchain/elfcopy/sections.c @@ -42,14 +42,12 @@ static void check_section_rename(struct elfcopy *ecp, struct section *s); static void filter_reloc(struct elfcopy *ecp, struct section *s); static int get_section_flags(struct elfcopy *ecp, const char *name); static void insert_sections(struct elfcopy *ecp); -static void insert_to_strtab(struct section *t, const char *s); static int is_append_section(struct elfcopy *ecp, const char *name); static int is_compress_section(struct elfcopy *ecp, const char *name); static int is_debug_section(const char *name); static int is_dwo_section(const char *name); static int is_modify_section(struct elfcopy *ecp, const char *name); static int is_print_section(struct elfcopy *ecp, const char *name); -static int lookup_string(struct section *t, const char *s); static void modify_section(struct elfcopy *ecp, struct section *s); static void pad_section(struct elfcopy *ecp, struct section *s); static void print_data(const char *d, size_t sz); @@ -119,21 +117,19 @@ is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info) errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", elf_errmsg(-1)); - is = NULL; - while ((is = elf_nextscn(ecp->ein, is)) != NULL) { - if (sh_info == elf_ndxscn(is)) { - if (gelf_getshdr(is, &ish) == NULL) - errx(EXIT_FAILURE, "gelf_getshdr failed: %s", - elf_errmsg(-1)); - if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == - NULL) - errx(EXIT_FAILURE, "elf_strptr failed: %s", - elf_errmsg(-1)); - if (is_remove_section(ecp, name)) - return (1); - else - return (0); - } + is = elf_getscn(ecp->ein, sh_info); + if (is != NULL) { + if (gelf_getshdr(is, &ish) == NULL) + errx(EXIT_FAILURE, "gelf_getshdr failed: %s", + elf_errmsg(-1)); + if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == + NULL) + errx(EXIT_FAILURE, "elf_strptr failed: %s", + elf_errmsg(-1)); + if (is_remove_section(ecp, name)) + return (1); + else + return (0); } elferr = elf_errno(); if (elferr != 0) @@ -314,18 +310,18 @@ insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail) { struct section *s; - if (!tail) { + if (tail || TAILQ_EMPTY(&ecp->v_sec) || + TAILQ_LAST(&ecp->v_sec, sectionlist)->off <= sec->off) { + TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list); + } else { TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { if (sec->off < s->off) { TAILQ_INSERT_BEFORE(s, sec, sec_list); - goto inc_nos; + break; } } } - TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list); - -inc_nos: if (sec->pseudo == 0) ecp->nos++; } @@ -1338,10 +1334,9 @@ insert_sections(struct elfcopy *ecp) void add_to_shstrtab(struct elfcopy *ecp, const char *name) { - struct section *s; - s = ecp->shstrtab; - insert_to_strtab(s, name); + if (elftc_string_table_insert(ecp->shstrtab->strtab, name) == 0) + errx(EXIT_FAILURE, "elftc_string_table_insert failed"); } void @@ -1351,6 +1346,9 @@ update_shdr(struct elfcopy *ecp, int update_link) GElf_Shdr osh; int elferr; + /* Finalize the section name string table (.shstrtab). */ + set_shstrtab(ecp); + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { if (s->pseudo) continue; @@ -1360,7 +1358,8 @@ update_shdr(struct elfcopy *ecp, int update_link) elf_errmsg(-1)); /* Find section name in string table and set sh_name. */ - osh.sh_name = lookup_string(ecp->shstrtab, s->name); + osh.sh_name = elftc_string_table_lookup(ecp->shstrtab->strtab, + s->name); /* * sh_link needs to be updated, since the index of the @@ -1410,11 +1409,12 @@ init_shstrtab(struct elfcopy *ecp) s->loadable = 0; s->type = SHT_STRTAB; s->vma = 0; + s->strtab = elftc_string_table_create(0); - insert_to_strtab(s, ""); - insert_to_strtab(s, ".symtab"); - insert_to_strtab(s, ".strtab"); - insert_to_strtab(s, ".shstrtab"); + add_to_shstrtab(ecp, ""); + add_to_shstrtab(ecp, ".symtab"); + add_to_shstrtab(ecp, ".strtab"); + add_to_shstrtab(ecp, ".shstrtab"); } void @@ -1423,6 +1423,7 @@ set_shstrtab(struct elfcopy *ecp) struct section *s; Elf_Data *data; GElf_Shdr sh; + const char *image; s = ecp->shstrtab; @@ -1455,18 +1456,19 @@ set_shstrtab(struct elfcopy *ecp) * which are reserved for this in the beginning of shstrtab. */ if (!(ecp->flags & SYMTAB_EXIST)) { - s->sz -= sizeof(".symtab\0.strtab"); - memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"), - s->sz); + elftc_string_table_remove(s->strtab, ".symtab"); + elftc_string_table_remove(s->strtab, ".strtab"); } + image = elftc_string_table_image(s->strtab, &s->sz); + sh.sh_size = s->sz; if (!gelf_update_shdr(s->os, &sh)) errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", elf_errmsg(-1)); data->d_align = 1; - data->d_buf = s->buf; + data->d_buf = __DECONST(char *, image); data->d_size = s->sz; data->d_off = 0; data->d_type = ELF_T_BYTE; @@ -1593,73 +1595,6 @@ add_gnu_debuglink(struct elfcopy *ecp) ecp->flags |= SEC_ADD; } -static void -insert_to_strtab(struct section *t, const char *s) -{ - const char *r; - char *b, *c; - size_t len, slen; - int append; - - if (t->sz == 0) { - t->cap = 512; - if ((t->buf = malloc(t->cap)) == NULL) - err(EXIT_FAILURE, "malloc failed"); - } - - slen = strlen(s); - append = 0; - b = t->buf; - for (c = b; c < b + t->sz;) { - len = strlen(c); - if (!append && len >= slen) { - r = c + (len - slen); - if (strcmp(r, s) == 0) - return; - } else if (len < slen && len != 0) { - r = s + (slen - len); - if (strcmp(c, r) == 0) { - t->sz -= len + 1; - memmove(c, c + len + 1, t->sz - (c - b)); - append = 1; - continue; - } - } - c += len + 1; - } - - while (t->sz + slen + 1 >= t->cap) { - t->cap *= 2; - if ((t->buf = realloc(t->buf, t->cap)) == NULL) - err(EXIT_FAILURE, "realloc failed"); - } - b = t->buf; - strncpy(&b[t->sz], s, slen); - b[t->sz + slen] = '\0'; - t->sz += slen + 1; -} - -static int -lookup_string(struct section *t, const char *s) -{ - const char *b, *c, *r; - size_t len, slen; - - slen = strlen(s); - b = t->buf; - for (c = b; c < b + t->sz;) { - len = strlen(c); - if (len >= slen) { - r = c + (len - slen); - if (strcmp(r, s) == 0) - return (r - b); - } - c += len + 1; - } - - return (-1); -} - static uint32_t crctable[256] = { 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, diff --git a/contrib/elftoolchain/libelf/_libelf.h b/contrib/elftoolchain/libelf/_libelf.h index f7f8d9a151c2..a3a43285cb13 100644 --- a/contrib/elftoolchain/libelf/_libelf.h +++ b/contrib/elftoolchain/libelf/_libelf.h @@ -30,6 +30,7 @@ #define __LIBELF_H_ #include +#include #include "_libelf_config.h" @@ -80,6 +81,9 @@ extern struct _libelf_globals _libelf; #define LIBELF_F_SHDRS_LOADED 0x200000U /* whether all shdrs were read in */ #define LIBELF_F_SPECIAL_FILE 0x400000U /* non-regular file */ +RB_HEAD(scntree, _Elf_Scn); +RB_PROTOTYPE(scntree, _Elf_Scn, e_scn, elfscn_cmp); + struct _Elf { int e_activations; /* activation count */ unsigned int e_byteorder; /* ELFDATA* */ @@ -122,7 +126,7 @@ struct _Elf { Elf32_Phdr *e_phdr32; Elf64_Phdr *e_phdr64; } e_phdr; - STAILQ_HEAD(, _Elf_Scn) e_scn; /* section list */ + struct scntree e_scn; /* sections */ size_t e_nphdr; /* number of Phdr entries */ size_t e_nscn; /* number of sections */ size_t e_strndx; /* string table section index */ @@ -147,7 +151,7 @@ struct _Elf_Scn { } s_shdr; STAILQ_HEAD(, _Libelf_Data) s_data; /* translated data */ STAILQ_HEAD(, _Libelf_Data) s_rawdata; /* raw data */ - STAILQ_ENTRY(_Elf_Scn) s_next; + RB_ENTRY(_Elf_Scn) s_tree; struct _Elf *s_elf; /* parent ELF descriptor */ unsigned int s_flags; /* flags for the section as a whole */ size_t s_ndx; /* index# for this section */ diff --git a/contrib/elftoolchain/libelf/elf_end.c b/contrib/elftoolchain/libelf/elf_end.c index 3f32ebbee8ec..e20dbe10d99e 100644 --- a/contrib/elftoolchain/libelf/elf_end.c +++ b/contrib/elftoolchain/libelf/elf_end.c @@ -39,8 +39,8 @@ ELFTC_VCSID("$Id: elf_end.c 3174 2015-03-27 17:13:41Z emaste $"); int elf_end(Elf *e) { - Elf *sv; Elf_Scn *scn, *tscn; + Elf *sv; if (e == NULL || e->e_activations == 0) return (0); @@ -66,8 +66,7 @@ elf_end(Elf *e) /* * Reclaim all section descriptors. */ - STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, - tscn) + RB_FOREACH_SAFE(scn, scntree, &e->e_u.e_elf.e_scn, tscn) scn = _libelf_release_scn(scn); break; case ELF_K_NUM: diff --git a/contrib/elftoolchain/libelf/elf_scn.c b/contrib/elftoolchain/libelf/elf_scn.c index b72fef66c46b..29da21a4261e 100644 --- a/contrib/elftoolchain/libelf/elf_scn.c +++ b/contrib/elftoolchain/libelf/elf_scn.c @@ -38,6 +38,19 @@ ELFTC_VCSID("$Id: elf_scn.c 3632 2018-10-10 21:12:43Z jkoshy $"); +static int +elfscn_cmp(struct _Elf_Scn *s1, struct _Elf_Scn *s2) +{ + + if (s1->s_ndx < s2->s_ndx) + return (-1); + if (s1->s_ndx > s2->s_ndx) + return (1); + return (0); +} + +RB_GENERATE(scntree, _Elf_Scn, s_tree, elfscn_cmp); + /* * Load an ELF section table and create a list of Elf_Scn structures. */ @@ -95,9 +108,9 @@ _libelf_load_section_headers(Elf *e, void *ehdr) */ i = 0; - if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) { - assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) == - STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next)); + if (!RB_EMPTY(&e->e_u.e_elf.e_scn)) { + assert(RB_MIN(scntree, &e->e_u.e_elf.e_scn) == + RB_MAX(scntree, &e->e_u.e_elf.e_scn)); i = 1; src += fsz; @@ -148,10 +161,16 @@ elf_getscn(Elf *e, size_t index) _libelf_load_section_headers(e, ehdr) == 0) return (NULL); - STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) + for (s = RB_ROOT(&e->e_u.e_elf.e_scn); s != NULL;) { if (s->s_ndx == index) return (s); + if (s->s_ndx < index) + s = RB_RIGHT(s, s_tree); + else + s = RB_LEFT(s, s_tree); + } + LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } @@ -201,7 +220,7 @@ elf_newscn(Elf *e) _libelf_load_section_headers(e, ehdr) == 0) return (NULL); - if (STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) { + if (RB_EMPTY(&e->e_u.e_elf.e_scn)) { assert(e->e_u.e_elf.e_nscn == 0); if ((scn = _libelf_allocate_scn(e, (size_t) SHN_UNDEF)) == NULL) @@ -231,5 +250,5 @@ elf_nextscn(Elf *e, Elf_Scn *s) } return (s == NULL ? elf_getscn(e, (size_t) 1) : - STAILQ_NEXT(s, s_next)); + RB_NEXT(scntree, &e->e_u.e_elf.e_scn, s)); } diff --git a/contrib/elftoolchain/libelf/elf_update.c b/contrib/elftoolchain/libelf/elf_update.c index 755f33690e36..431b473eef8d 100644 --- a/contrib/elftoolchain/libelf/elf_update.c +++ b/contrib/elftoolchain/libelf/elf_update.c @@ -452,7 +452,7 @@ _libelf_resync_sections(Elf *e, off_t rc, struct _Elf_Extent_List *extents) * Make a pass through sections, computing the extent of each * section. */ - STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) { + RB_FOREACH(s, scntree, &e->e_u.e_elf.e_scn) { if (ec == ELFCLASS32) sh_type = s->s_shdr.s_shdr32.sh_type; else @@ -980,7 +980,7 @@ _libelf_write_shdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex) fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1); - STAILQ_FOREACH(scn, &e->e_u.e_elf.e_scn, s_next) { + RB_FOREACH(scn, scntree, &e->e_u.e_elf.e_scn) { if (ec == ELFCLASS32) src.d_buf = &scn->s_shdr.s_shdr32; else @@ -1142,7 +1142,7 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents) e->e_flags &= ~ELF_F_DIRTY; - STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn) + RB_FOREACH_SAFE(scn, scntree, &e->e_u.e_elf.e_scn, tscn) _libelf_release_scn(scn); if (e->e_class == ELFCLASS32) { diff --git a/contrib/elftoolchain/libelf/libelf_allocate.c b/contrib/elftoolchain/libelf/libelf_allocate.c index 0a74facc9fc4..f9dab08d1ed6 100644 --- a/contrib/elftoolchain/libelf/libelf_allocate.c +++ b/contrib/elftoolchain/libelf/libelf_allocate.c @@ -76,7 +76,7 @@ _libelf_init_elf(Elf *e, Elf_Kind kind) switch (kind) { case ELF_K_ELF: - STAILQ_INIT(&e->e_u.e_elf.e_scn); + RB_INIT(&e->e_u.e_elf.e_scn); break; default: break; @@ -111,7 +111,7 @@ _libelf_release_elf(Elf *e) break; } - assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); + assert(RB_EMPTY(&e->e_u.e_elf.e_scn)); if (e->e_flags & LIBELF_F_AR_HEADER) { arh = e->e_hdr.e_arhdr; @@ -174,7 +174,7 @@ _libelf_allocate_scn(Elf *e, size_t ndx) STAILQ_INIT(&s->s_data); STAILQ_INIT(&s->s_rawdata); - STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next); + RB_INSERT(scntree, &e->e_u.e_elf.e_scn, s); return (s); } @@ -202,7 +202,7 @@ _libelf_release_scn(Elf_Scn *s) assert(e != NULL); - STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next); + RB_REMOVE(scntree, &e->e_u.e_elf.e_scn, s); free(s); diff --git a/contrib/elftoolchain/libelf/libelf_ehdr.c b/contrib/elftoolchain/libelf/libelf_ehdr.c index 38e4e74e14d2..0a761956418e 100644 --- a/contrib/elftoolchain/libelf/libelf_ehdr.c +++ b/contrib/elftoolchain/libelf/libelf_ehdr.c @@ -46,7 +46,7 @@ _libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum, uint32_t shtype; _libelf_translator_function *xlator; - assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); + assert(RB_EMPTY(&e->e_u.e_elf.e_scn)); fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1); assert(fsz > 0); diff --git a/contrib/elftoolchain/libelf/libelf_extended.c b/contrib/elftoolchain/libelf/libelf_extended.c index 96765a8293e1..21be11c87fab 100644 --- a/contrib/elftoolchain/libelf/libelf_extended.c +++ b/contrib/elftoolchain/libelf/libelf_extended.c @@ -39,7 +39,7 @@ _libelf_getscn0(Elf *e) { Elf_Scn *s; - if ((s = STAILQ_FIRST(&e->e_u.e_elf.e_scn)) != NULL) + if ((s = RB_MIN(scntree, &e->e_u.e_elf.e_scn)) != NULL) return (s); return (_libelf_allocate_scn(e, (size_t) SHN_UNDEF)); diff --git a/contrib/elftoolchain/libelftc/elftc_string_table.c b/contrib/elftoolchain/libelftc/elftc_string_table.c index bba9ac6a76cd..1ecdb65c92d1 100644 --- a/contrib/elftoolchain/libelftc/elftc_string_table.c +++ b/contrib/elftoolchain/libelftc/elftc_string_table.c @@ -170,8 +170,6 @@ elftc_string_table_destroy(Elftc_String_Table *st) free(s); free(st->st_string_pool); free(st); - - return; } Elftc_String_Table * @@ -318,7 +316,7 @@ elftc_string_table_insert(Elftc_String_Table *st, const char *string) if ((ste = malloc(sizeof(*ste))) == NULL) return (0); if ((ste->ste_idx = elftc_string_table_add_to_pool(st, - string)) == 0) { + string)) == 0) { free(ste); return (0); } diff --git a/contrib/elftoolchain/libelftc/elftc_string_table_create.3 b/contrib/elftoolchain/libelftc/elftc_string_table_create.3 index 387ad72a3727..36c7290d9f46 100644 --- a/contrib/elftoolchain/libelftc/elftc_string_table_create.3 +++ b/contrib/elftoolchain/libelftc/elftc_string_table_create.3 @@ -144,7 +144,7 @@ looks up the string referenced by argument in the string table specified by argument .Ar table , and if found, returns the offset associated with the string. -The returned offset will be valid till the next call to function +The returned offset will be valid until the next call to .Fn elftc_string_table_image . .Pp Function