add KPATCH_IGNORE_SECTION support

This macro is for ignoring sections that may change as a side effect of
another change or might be a non-bundlable section; that is one that
does not honor -ffunction-section and create a one-to-one relation from
function symbol to section.

Signed-off-by: Seth Jennings <sjenning@redhat.com>
This commit is contained in:
Seth Jennings 2014-07-24 14:54:20 -05:00
parent 11f8f8da76
commit 8ac20f5475
2 changed files with 63 additions and 1 deletions

View File

@ -17,6 +17,17 @@ struct kpatch_unload {
char *objname; /* filled in by create-diff-object */
};
/*
* KPATCH_IGNORE_SECTION macro
*
* This macro is for ignoring sections that may change as a side effect of
* another change or might be a non-bundlable section; that is one that does
* not honor -ffunction-section and create a one-to-one relation from function
* symbol to section.
*/
#define KPATCH_IGNORE_SECTION(_sec) \
char *__UNIQUE_ID(kpatch_ignore_section_) __section(.kpatch.ignore.sections) = _sec;
/*
* KPATCH_IGNORE_FUNCTION macro
*

View File

@ -620,11 +620,15 @@ void kpatch_compare_correlated_symbol(struct symbol *sym)
if (sym1->sym.st_info != sym2->sym.st_info ||
sym1->sym.st_other != sym2->sym.st_other ||
(sym1->sec && sym2->sec && sym1->sec->twin != sym2->sec) ||
(sym1->sec && !sym2->sec) ||
(sym2->sec && !sym1->sec))
DIFF_FATAL("symbol info mismatch: %s", sym1->name);
if (sym1->sec && sym2->sec && sym1->sec->twin != sym2->sec) {
log_normal("NOTICE: symbol %s has changed sections\n", sym1->name);
sym1->status = CHANGED;
}
if (sym1->type == STT_OBJECT &&
sym1->sym.st_size != sym2->sym.st_size)
DIFF_FATAL("object size mismatch: %s", sym1->name);
@ -1484,6 +1488,52 @@ void kpatch_include_debug_sections(struct kpatch_elf *kelf)
}
}
void kpatch_mark_ignored_sections_same(struct kpatch_elf *kelf)
{
struct section *sec, *strsec, *ignoresec;
struct symbol *sym;
struct rela *rela;
char *name;
sec = find_section_by_name(&kelf->sections, ".kpatch.ignore.sections");
if (!sec)
return;
list_for_each_entry(rela, &sec->rela->relas, list) {
strsec = rela->sym->sec;
strsec->status = CHANGED;
/*
* Include the string section here. This is because the
* KPATCH_IGNORE_SECTION() macro is passed a literal string
* by the patch author, resulting in a change to the string
* section. If we don't include it, then we will potentially
* get a "changed section not included" error in
* kpatch_verify_patchability() if not other function based change
* also changes the string section. We could try to exclude each
* literal string added to the section by KPATCH_IGNORE_SECTION()
* from the section data comparison, but this is a simpler way.
*/
strsec->include = 1;
name = strsec->data->d_buf + rela->addend;
ignoresec = find_section_by_name(&kelf->sections, name);
if (!ignoresec)
ERROR("expected ignored section");
log_normal("ignoring section %s\n", name);
if (ignoresec->status != CHANGED)
ERROR("no change detected in ignored section %s\n", ignoresec->name);
ignoresec->status = SAME;
if (ignoresec->secsym)
ignoresec->secsym->status = SAME;
if (ignoresec->rela)
ignoresec->rela->status = SAME;
list_for_each_entry(sym, &kelf->symbols, list) {
if (sym->sec != sec)
continue;
sym->status = SAME;
}
}
}
void kpatch_mark_ignored_functions_same(struct kpatch_elf *kelf)
{
struct section *sec;
@ -2436,6 +2486,7 @@ int main(int argc, char *argv[])
kpatch_elf_free(kelf_base);
kpatch_mark_ignored_functions_same(kelf_patched);
kpatch_mark_ignored_sections_same(kelf_patched);
kpatch_process_special_sections(kelf_patched);