elfcopy: Use libelftc's string table routines to build .shstrtab.
This replaces some hand-rolled routines and is substantially faster since libelftc uses a hash table for lookups and insertions, whereas elfcopy would perform a linear scan of the table. PR: 234949 Reviewed by: emaste MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D20473
This commit is contained in:
parent
d7bcf73630
commit
bc589b723e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=348657
@ -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);
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -135,6 +135,8 @@ struct section {
|
||||
int pseudo;
|
||||
int nocopy;
|
||||
|
||||
Elftc_String_Table *strtab;
|
||||
|
||||
TAILQ_ENTRY(section) sec_list; /* next section */
|
||||
};
|
||||
|
||||
@ -313,7 +315,6 @@ struct sec_action *lookup_sec_act(struct elfcopy *_ecp,
|
||||
struct symop *lookup_symop_list(struct elfcopy *_ecp, const char *_name,
|
||||
unsigned int _op);
|
||||
void resync_sections(struct elfcopy *_ecp);
|
||||
void set_shstrtab(struct elfcopy *_ecp);
|
||||
void setup_phdr(struct elfcopy *_ecp);
|
||||
void update_shdr(struct elfcopy *_ecp, int _update_link);
|
||||
|
||||
|
@ -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
|
||||
@ -486,6 +483,9 @@ free_elf(struct elfcopy *ecp)
|
||||
/* Free symbol table buffers. */
|
||||
free_symtab(ecp);
|
||||
|
||||
/* Free section name string table. */
|
||||
elftc_string_table_destroy(ecp->shstrtab->strtab);
|
||||
|
||||
/* Free internal section list. */
|
||||
if (!TAILQ_EMPTY(&ecp->v_sec)) {
|
||||
TAILQ_FOREACH_SAFE(sec, &ecp->v_sec, sec_list, sec_temp) {
|
||||
|
@ -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);
|
||||
|
||||
@ -1336,10 +1335,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
|
||||
@ -1349,6 +1347,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;
|
||||
@ -1358,7 +1359,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
|
||||
@ -1408,19 +1410,22 @@ 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
|
||||
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;
|
||||
|
||||
@ -1453,19 +1458,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;
|
||||
@ -1591,73 +1598,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,
|
||||
|
Loading…
Reference in New Issue
Block a user