From 66d1b112903b4942cc1033a1be93ae79c1ecf8ef Mon Sep 17 00:00:00 2001 From: Zhipeng Xie Date: Fri, 2 Nov 2018 17:25:38 +0000 Subject: [PATCH 07/23] create-diff-object: create dynamic relocs for changed functions in this object Currently, we only create dynamic relocs for changed functions of other objects, but not this object. It will cause a problem like: original: funcA and funcB (funcA calls funcB) patch-1: funcA-1 and funcB-1 (funcA-1 calls funcB-1) patch-2: funcB-2 (funcA-1 should call funcB-2) But as we don't create dynamic relocs for funcA-1, it will call funcB-1 directly (not by jumping from funcB). So the new funcB-2 will not get called. This patch will create dynamic relocs for all the changed functions, including changed ones in this object. Reported-by: Xie Zhipeng Tested-by: Zhou Chengming Signed-off-by: Zhou Chengming Signed-off-by: Li Bin Signed-off-by: Zhipeng Xie --- kpatch-build/create-diff-object.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index ba2976b..8ce3b59 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -2900,6 +2900,14 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, */ if (may_need_dynrela(rela)) toc_rela(rela)->need_dynrela = 1; + if (rela->sym->sec) { + if (rela->sym->type == STT_FUNC && + rela->sym->status == CHANGED && + rela->sym->sec != sec->base && + sec->base->sym && + sec->base->sym->type == STT_FUNC) + toc_rela(rela)->need_dynrela = 1; + } } } @@ -2982,10 +2990,17 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, /* An unchanged local symbol */ ret = lookup_local_symbol(table, rela->sym->name, &result); - if (ret) - ERROR("lookup_local_symbol %s needed for %s", - rela->sym->name, sec->base->name); - + if (ret) { + /* + * maybe it is a global symbol converted in + * kpatch_create_patches_sections + */ + ret = lookup_global_symbol(table, + rela->sym->name, &result); + if (ret) + ERROR("lookup_local_symbol %s needed for %s", + rela->sym->name, sec->base->name); + } } else if (vmlinux) { /* -- 2.18.1