refactor copying symbols to output

Create a new function kpatch_copy_symbols() that copies symbols from
one kelf to another if the "select" function to return true for the
symbol.

Signed-off-by: Seth Jennings <sjenning@redhat.com>
This commit is contained in:
Seth Jennings 2014-03-20 16:03:43 -05:00
parent e51fd3d28b
commit fdf83f21c3

View File

@ -844,11 +844,56 @@ void kpatch_include_changed_functions(struct kpatch_elf *kelf)
}
}
int kpatch_copy_symbols(int startndx, struct kpatch_elf *src,
struct kpatch_elf *dst,
int (*select)(struct symbol *))
{
struct symbol *srcsym, *dstsym;
int i, index = startndx;
for_each_symbol(i, srcsym, &src->symbols) {
if (i == 0 || !srcsym->include)
continue;
if (select && !select(srcsym))
continue;
dstsym = &((struct symbol *)(dst->symbols.data))[index];
*dstsym = *srcsym;
dstsym->index = index;
dstsym->twino = srcsym;
srcsym->twino = dstsym;
index++;
if (srcsym->sec && srcsym->sec->twino)
dstsym->sym.st_shndx = srcsym->sec->twino->index;
srcsym->include = 0;
}
return index;
}
int is_file_sym(struct symbol *sym)
{
return sym->type == STT_FILE;
}
int is_local_func_sym(struct symbol *sym)
{
return sym->bind == STB_LOCAL && sym->type == STT_FUNC;
}
int is_local_sym(struct symbol *sym)
{
return sym->bind == STB_LOCAL;
}
void kpatch_generate_output(struct kpatch_elf *kelf, struct kpatch_elf **kelfout)
{
int sections_nr = 0, symbols_nr = 0, i, index;
struct section *sec, *secout;
struct symbol *sym, *symout;
struct symbol *sym;
struct kpatch_elf *out;
/* count output sections */
@ -914,69 +959,21 @@ void kpatch_generate_output(struct kpatch_elf *kelf, struct kpatch_elf **kelfout
}
}
/*
* Copy functions to the output kelf and reindex. Once the symbol is
* copied, its include field is set to zero so it isn't copied again
* by a subsequent kpatch_copy_symbols() call.
*/
/* start at 1 to skip over symbol 0 (all zeros) */
index = 1;
/* copy local FUNC/FILE syms to kelf symbols */
/* TODO: this for block is copeid 3 times, refactor! */
for_each_symbol(i, sym, &kelf->symbols) {
if (i == 0 || !sym->include)
continue;
if (sym->bind == STB_GLOBAL ||
(sym->type != STT_FUNC && sym->type != STT_FILE))
continue;
symout = &((struct symbol *)(out->symbols.data))[index];
*symout = *sym;
symout->index = index;
symout->twino = sym;
sym->twino = symout;
index++;
if (sym->sec && sym->sec->twino)
symout->sym.st_shndx = sym->sec->twino->index;
sym->include = 0;
}
/* copy local syms to output kelf symbols, link to kelf, and reindex */
for_each_symbol(i, sym, &kelf->symbols) {
if (i == 0 || !sym->include)
continue;
if (sym->bind == STB_GLOBAL)
continue;
symout = &((struct symbol *)(out->symbols.data))[index];
*symout = *sym;
symout->index = index;
symout->twino = sym;
sym->twino = symout;
index++;
if (sym->sec && sym->sec->twino)
symout->sym.st_shndx = sym->sec->twino->index;
sym->include = 0;
}
/* copy global syms to output kelf symbols, link to kelf, and reindex */
for_each_symbol(i, sym, &kelf->symbols) {
if (i == 0 || !sym->include)
continue;
symout = &((struct symbol *)(out->symbols.data))[index];
*symout = *sym;
symout->index = index;
symout->twino = sym;
sym->twino = symout;
index++;
if (sym->sec && sym->sec->twino)
symout->sym.st_shndx = sym->sec->twino->index;
sym->include = 0;
}
/* copy (LOCAL) FILE sym */
index = kpatch_copy_symbols(index, kelf, out, is_file_sym);
/* copy LOCAL FUNC syms */
index = kpatch_copy_symbols(index, kelf, out, is_local_func_sym);
/* copy all other LOCAL syms */
index = kpatch_copy_symbols(index, kelf, out, is_local_sym);
/* copy all other (GLOBAL) syms */
index = kpatch_copy_symbols(index, kelf, out, NULL);
*kelfout = out;
}