diff options
author | Ed Maste <emaste@FreeBSD.org> | 2019-06-29 15:27:18 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2019-06-29 15:27:18 +0000 |
commit | a5b08c1484eac2c6a65e726f550b3189ff84c6c8 (patch) | |
tree | 01cd9d6d76e2c378b391422460c6f233ead08179 /elfcopy/sections.c | |
parent | 2b92b30119ed91ed88f102ba9ecc40cd1c046a65 (diff) |
Notes
Diffstat (limited to 'elfcopy/sections.c')
-rw-r--r-- | elfcopy/sections.c | 168 |
1 files changed, 61 insertions, 107 deletions
diff --git a/elfcopy/sections.c b/elfcopy/sections.c index d9d0edda676ac..4d45d82a18e75 100644 --- a/elfcopy/sections.c +++ b/elfcopy/sections.c @@ -34,7 +34,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: sections.c 3646 2018-10-27 02:25:39Z emaste $"); +ELFTC_VCSID("$Id: sections.c 3758 2019-06-28 01:16:50Z emaste $"); static void add_gnu_debuglink(struct elfcopy *ecp); static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); @@ -42,19 +42,18 @@ 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); static void print_section(struct section *s); static void *read_section(struct section *s, size_t *size); +static void set_shstrtab(struct elfcopy *ecp); static void update_reloc(struct elfcopy *ecp, struct section *s); static void update_section_group(struct elfcopy *ecp, struct section *s); @@ -119,21 +118,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 +311,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++; } @@ -711,13 +708,13 @@ filter_reloc(struct elfcopy *ecp, struct section *s) #define COPYREL(REL, SZ) do { \ if (nrels == 0) { \ if ((REL##SZ = malloc(cap * \ - sizeof(Elf##SZ##_Rel))) == NULL) \ + sizeof(*REL##SZ))) == NULL) \ err(EXIT_FAILURE, "malloc failed"); \ } \ if (nrels >= cap) { \ cap *= 2; \ if ((REL##SZ = realloc(REL##SZ, cap * \ - sizeof(Elf##SZ##_Rel))) == NULL) \ + sizeof(*REL##SZ))) == NULL) \ err(EXIT_FAILURE, "realloc failed"); \ } \ REL##SZ[nrels].r_offset = REL.r_offset; \ @@ -1335,10 +1332,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 @@ -1348,6 +1344,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; @@ -1357,7 +1356,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 @@ -1395,7 +1395,23 @@ update_shdr(struct elfcopy *ecp, int update_link) void init_shstrtab(struct elfcopy *ecp) { + Elf_Scn *shstrtab; + GElf_Shdr shdr; struct section *s; + size_t indx, sizehint; + + if (elf_getshstrndx(ecp->ein, &indx) != 0) { + shstrtab = elf_getscn(ecp->ein, indx); + if (shstrtab == NULL) + errx(EXIT_FAILURE, "elf_getscn failed: %s", + elf_errmsg(-1)); + if (gelf_getshdr(shstrtab, &shdr) != &shdr) + errx(EXIT_FAILURE, "gelf_getshdr failed: %s", + elf_errmsg(-1)); + sizehint = shdr.sh_size; + } else { + sizehint = 0; + } if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL) err(EXIT_FAILURE, "calloc failed"); @@ -1407,19 +1423,22 @@ init_shstrtab(struct elfcopy *ecp) s->loadable = 0; s->type = SHT_STRTAB; s->vma = 0; + s->strtab = elftc_string_table_create(sizehint); - 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 +static void set_shstrtab(struct elfcopy *ecp) { struct section *s; Elf_Data *data; GElf_Shdr sh; + const char *image; + size_t sz; s = ecp->shstrtab; @@ -1452,19 +1471,21 @@ 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"); } - sh.sh_size = s->sz; + image = elftc_string_table_image(s->strtab, &sz); + s->sz = sz; + + sh.sh_size = 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_size = s->sz; + data->d_buf = (void *)(uintptr_t)image; + data->d_size = sz; data->d_off = 0; data->d_type = ELF_T_BYTE; data->d_version = EV_CURRENT; @@ -1590,73 +1611,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, |