From 84618404e06a87032904a45064600be7884862c9 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Tue, 22 Jul 2014 16:01:23 -0500 Subject: [PATCH] add support for manually ignore functions This commit adds the KPATCH_IGNORE_FUNC() macro for ignoring functions that may change as a side effect of a change in another function. The WARN class of macros, for example, embed the line number in an instruction, which will cause the function to be detected as changed when, in fact, there has been no functional change. Signed-off-by: Seth Jennings --- kmod/patch/kpatch-macros.h | 11 +++++++++++ kpatch-build/create-diff-object.c | 27 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/kmod/patch/kpatch-macros.h b/kmod/patch/kpatch-macros.h index 8f31637..0290c82 100644 --- a/kmod/patch/kpatch-macros.h +++ b/kmod/patch/kpatch-macros.h @@ -17,6 +17,17 @@ struct kpatch_unload { char *objname; /* filled in by create-diff-object */ }; +/* + * KPATCH_IGNORE_FUNCTION macro + * + * This macro is for ignoring functions that may change as a side effect of a + * change in another function. The WARN class of macros, for example, embed + * the line number in an instruction, which will cause the function to be + * detected as changed when, in fact, there has been no functional change. + */ +#define KPATCH_IGNORE_FUNCTION(_fn) \ + void *__kpatch_ignore_func_##_fn __section(.kpatch.ignore.funcs) = _fn; + /* * KPATCH_LOAD_HOOK macro * diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 3f51823..bcf885c 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -1376,6 +1376,32 @@ void kpatch_include_debug_sections(struct kpatch_elf *kelf) } } +void kpatch_mark_ignored_funcs_same(struct kpatch_elf *kelf) +{ + struct section *sec; + struct rela *rela; + + sec = find_section_by_name(&kelf->sections, ".kpatch.ignore.funcs"); + if (!sec) + return; + + list_for_each_entry(rela, &sec->rela->relas, list) { + if (!rela->sym->sec) + ERROR("expected bundled symbol"); + if (rela->sym->type != STT_FUNC) + ERROR("expected function symbol"); + log_normal("ignoring function %s\n", rela->sym->name); + if (rela->sym->status != CHANGED) + log_normal("NOTICE: no change detected in function %s, unnecessary KPATCH_IGNORE_FUNC()?\n", rela->sym->name); + rela->sym->status = SAME; + rela->sym->sec->status = SAME; + if (rela->sym->sec->secsym) + rela->sym->sec->secsym->status = SAME; + if (rela->sym->sec->rela) + rela->sym->sec->rela->status = SAME; + } +} + void kpatch_process_special_sections(struct kpatch_elf *kelf) { struct special_section *special; @@ -2306,6 +2332,7 @@ int main(int argc, char *argv[]) * in vmlinux can be linked to. */ kpatch_replace_sections_syms(kelf_patched); + kpatch_mark_ignored_funcs_same(kelf_patched); kpatch_process_special_sections(kelf_patched);