From bd2589530c713192aea7f4044a66a352a220dfe9 Mon Sep 17 00:00:00 2001 From: Artem Savkov Date: Tue, 12 Jun 2018 16:05:30 +0200 Subject: [PATCH] create-diff-object: add symbol relations Add a function that would detect parent/child symbol relations. So far it only supports .cold.* symbols as children. Signed-off-by: Artem Savkov --- kpatch-build/create-diff-object.c | 35 +++++++++++++++++++++++++++++++ kpatch-build/kpatch-elf.h | 2 ++ 2 files changed, 37 insertions(+) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index d242d01..f2aca55 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -183,6 +183,38 @@ static void kpatch_bundle_symbols(struct kpatch_elf *kelf) } } +/* + * During optimization gcc may move unlikely execution branches into *.cold + * subfunctions. kpatch_detect_child_functions detects such subfunctions and + * crossreferences them with their parent functions through parent/child + * pointers. + */ +static void kpatch_detect_child_functions(struct kpatch_elf *kelf) +{ + struct symbol *sym; + + list_for_each_entry(sym, &kelf->symbols, list) { + char *coldstr; + + coldstr = strstr(sym->name, ".cold."); + if (coldstr != NULL) { + char *pname; + + pname = strndup(sym->name, coldstr - sym->name); + if (!pname) + ERROR("strndup"); + + sym->parent = find_symbol_by_name(&kelf->symbols, pname); + free(pname); + + if (!sym->parent) + ERROR("failed to find parent function for %s", sym->name); + + sym->parent->child = sym; + } + } +} + /* * This function detects whether the given symbol is a "special" static local * variable (for lack of a better term). @@ -3163,6 +3195,9 @@ int main(int argc, char *argv[]) kpatch_bundle_symbols(kelf_base); kpatch_bundle_symbols(kelf_patched); + kpatch_detect_child_functions(kelf_base); + kpatch_detect_child_functions(kelf_patched); + kpatch_compare_elf_headers(kelf_base->elf, kelf_patched->elf); kpatch_check_program_headers(kelf_base->elf); kpatch_check_program_headers(kelf_patched->elf); diff --git a/kpatch-build/kpatch-elf.h b/kpatch-build/kpatch-elf.h index bec6398..590aa6c 100644 --- a/kpatch-build/kpatch-elf.h +++ b/kpatch-build/kpatch-elf.h @@ -70,6 +70,8 @@ struct section { struct symbol { struct list_head list; struct symbol *twin; + struct symbol *parent; + struct symbol *child; struct section *sec; GElf_Sym sym; char *name;