From d1bbff5da464148e5d277b601a31d7872b4e376b Mon Sep 17 00:00:00 2001 From: Zhipeng Xie Date: Fri, 2 Nov 2018 17:26:00 +0000 Subject: [PATCH 1015/1015] create-diff-object: exclude line only change for arm64 exclude line only change for arm64 by compare mov instruction except immediate part. Signed-off-by: Zhipeng Xie --- kpatch-build/create-diff-object.c | 71 ++++++++++++++++++++++++++++++++++++- 1 files changed, 70 insertions(+), 1 deletions(-) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index f8f3e15..12d8bd6 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -609,6 +609,68 @@ static int kpatch_line_macro_change_only(struct section *sec) return 0; } #endif +#define ARM64_INSTR_LEN 4 +static int arm64_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; +} + static void kpatch_compare_sections(struct list_head *seclist) { @@ -624,7 +686,14 @@ static void kpatch_compare_sections(struct list_head *seclist) /* exclude WARN-only, might_sleep changes */ list_for_each_entry(sec, seclist, list) { - if (kpatch_line_macro_change_only(sec)) { + int line_only; + if (arch == EM_X86_64) + line_only = kpatch_line_macro_change_only(sec); + else if (arch == EM_AARCH64) + line_only = arm64_kpatch_line_macro_change_only(sec); + else + line_only = 0; + if (line_only) { log_debug("reverting macro / line number section %s status to SAME\n", sec->name); sec->status = SAME; -- 1.7.5.4