From b71b6e5f46fdc3f1b709b58777cb0da7ec9fc008 Mon Sep 17 00:00:00 2001 From: Zhipeng Xie Date: Sun, 14 Nov 2021 17:26:59 +0800 Subject: [PATCH 03/24] create-diff-object:support kpatch_line_macro_change_only on aarch64 implement kpatch_line_macro_change_only on aarch64 Signed-off-by: Zhipeng Xie --- kpatch-build/create-diff-object.c | 63 +++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 6c28280..c20f75e 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -757,6 +757,69 @@ static bool kpatch_line_macro_change_only(struct section *sec) return true; } +#elif __aarch64__ +#define ARM64_INSTR_LEN 4 + +static bool kpatch_line_macro_change_only(struct section *sec) +{ + unsigned long start1, start2, size, offset; + struct rela *rela; + int lineonly = 0, found; + unsigned int mov_imm_mask = ((1<<16) - 1)<<5; + + if (sec->status != CHANGED || + is_rela_section(sec) || + !is_text_section(sec) || + sec->sh.sh_size != sec->twin->sh.sh_size || + !sec->rela || + sec->rela->status != SAME) + return 0; + + start1 = (unsigned long)sec->twin->data->d_buf; + start2 = (unsigned long)sec->data->d_buf; + size = sec->sh.sh_size; + for (offset = 0; offset < size; offset += ARM64_INSTR_LEN) { + if (!memcmp((void *)start1 + offset, (void *)start2 + offset, + ARM64_INSTR_LEN)) + continue; + + /* verify it's a mov immediate to w1 */ + if ((*(int *)(start1 + offset) & ~mov_imm_mask) != + (*(int *)(start2 + offset) & ~mov_imm_mask)) + return 0; + + found = 0; + list_for_each_entry(rela, &sec->rela->relas, list) { + if (rela->offset < offset + ARM64_INSTR_LEN) + continue; + if (rela->string) + continue; + if (!strncmp(rela->sym->name, "__warned.", 9)) + continue; + if (!strncmp(rela->sym->name, "warn_slowpath_", 14) || + (!strcmp(rela->sym->name, "__warn_printk")) || + (!strcmp(rela->sym->name, "__might_sleep")) || + (!strcmp(rela->sym->name, "___might_sleep")) || + (!strcmp(rela->sym->name, "__might_fault")) || + (!strcmp(rela->sym->name, "printk")) || + (!strcmp(rela->sym->name, "lockdep_rcu_suspicious"))) { + found = 1; + break; + } + return 0; + } + if (!found) + return 0; + + lineonly = 1; + } + + if (!lineonly) + ERROR("no instruction changes detected for changed section %s", + sec->name); + + return 1; +} #else static bool kpatch_line_macro_change_only(struct section *sec) { -- 2.23.0