rebase from upstream v0.9.5

Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
This commit is contained in:
Zhipeng Xie 2021-11-16 12:10:06 +08:00
parent 2bb573342c
commit 4424f7bf7e
50 changed files with 1367 additions and 2658 deletions

View File

@ -0,0 +1,172 @@
From 821e6cb24778bd063d1e8ad097d4bd4c81973091 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 20 Dec 2018 04:55:38 +0000
Subject: [PATCH 01/24] kpatch: add aarch64 support
1.use R_AARCH64_ABS64 for aarch64
2.add find_special_section_data_arm64 for arm64:
arm64 kernel have no paravirt_patch_site or orc_entry structure
in vmlinux, we don't need to check these two struct for arm64.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/Makefile | 4 +++
kpatch-build/create-diff-object.c | 14 ++++++----
kpatch-build/kpatch-build | 46 +++++++++++++++++++++++++++++++
kpatch-build/kpatch-elf.c | 2 +-
4 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/kpatch-build/Makefile b/kpatch-build/Makefile
index 50899b6..423c32a 100644
--- a/kpatch-build/Makefile
+++ b/kpatch-build/Makefile
@@ -14,6 +14,10 @@ ifeq ($(ARCH),x86_64)
SOURCES += insn/insn.c insn/inat.c
INSN = insn/insn.o insn/inat.o
insn/%.o: CFLAGS := $(filter-out -Wconversion, $(CFLAGS))
+else ifeq ($(ARCH),aarch64)
+SOURCES += insn/insn.c insn/inat.c
+INSN = insn/insn.o insn/inat.o
+insn/%.o: CFLAGS := $(filter-out -Wconversion, $(CFLAGS))
else ifeq ($(ARCH),ppc64le)
SOURCES += gcc-plugins/ppc64le-plugin.c
PLUGIN = gcc-plugins/ppc64le-plugin.so
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 6a4848a..ca55180 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -62,6 +62,8 @@
#ifdef __powerpc64__
#define ABSOLUTE_RELA_TYPE R_PPC64_ADDR64
+#elif __aarch64__
+#define ABSOLUTE_RELA_TYPE R_AARCH64_ABS64
#else
#define ABSOLUTE_RELA_TYPE R_X86_64_64
#endif
@@ -1536,7 +1538,7 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
continue;
}
-#ifdef __powerpc64__
+#if defined(__powerpc64__) || defined(__aarch64__)
add_off = 0;
#else
if (rela->type == R_X86_64_PC32 ||
@@ -2028,7 +2030,7 @@ static int printk_index_group_size(struct kpatch_elf *kelf, int offset)
return size;
}
-#ifdef __x86_64__
+#if defined(__x86_64__) || defined(__aarch64__)
static int parainstructions_group_size(struct kpatch_elf *kelf, int offset)
{
static int size = 0;
@@ -2177,7 +2179,7 @@ static struct special_section special_sections[] = {
.name = ".printk_index",
.group_size = printk_index_group_size,
},
-#ifdef __x86_64__
+#if defined(__x86_64__) || defined(__aarch64__)
{
.name = ".smp_locks",
.group_size = smp_locks_group_size,
@@ -2990,7 +2992,9 @@ static int function_ptr_rela(const struct rela *rela)
rela_toc->addend == (int)rela_toc->sym->sym.st_value &&
(rela->type == R_X86_64_32S ||
rela->type == R_PPC64_TOC16_HA ||
- rela->type == R_PPC64_TOC16_LO_DS));
+ rela->type == R_PPC64_TOC16_LO_DS ||
+ rela->type == R_AARCH64_ADR_PREL_PG_HI21 ||
+ rela->type == R_AARCH64_ADD_ABS_LO12_NC));
}
static bool need_dynrela(struct lookup_table *table, struct section *sec, const struct rela *rela)
@@ -3479,7 +3483,7 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
rela->type = R_X86_64_PC32;
}
-#else /* __powerpc64__ */
+#else /* __powerpc64__ || __aarch64__ */
{
bool found = false;
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index eedf383..ad3a079 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -375,12 +375,58 @@ find_special_section_data_ppc64le() {
return
}
+find_special_section_data_aarch64() {
+
+ [[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_j=1"
+
+ # If $AWK_OPTIONS are blank gawk would treat "" as a blank script
+ # shellcheck disable=SC2086
+ SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
+ gawk --non-decimal-data $AWK_OPTIONS '
+ BEGIN { a = b = e = j = 0 }
+
+ # Set state if name matches
+ a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
+ b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
+ e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
+ j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
+
+ # Reset state unless this abbrev describes the struct size
+ a == 1 && !/DW_AT_byte_size/ { a = 0; next }
+ b == 1 && !/DW_AT_byte_size/ { b = 0; next }
+ e == 1 && !/DW_AT_byte_size/ { e = 0; next }
+ j == 1 && !/DW_AT_byte_size/ { j = 0; next }
+
+ # Now that we know the size, stop parsing for it
+ a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
+ b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2}
+ e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
+ j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
+
+ # Bail out once we have everything
+ a == 2 && b == 2 && e == 2 && (j == 2 || skip_j) {exit}')"
+
+ [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
+
+ [[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
+ [[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
+ [[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct exception_table_entry size"
+ [[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]] && die "can't find special struct jump_entry size"
+
+ return
+}
+
find_special_section_data() {
if [[ "$ARCH" = "ppc64le" ]]; then
find_special_section_data_ppc64le
return
fi
+ if [[ "$ARCH" = "aarch64" ]]; then
+ find_special_section_data_aarch64
+ return
+ fi
+
[[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
[[ "$CONFIG_UNWINDER_ORC" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_o=1"
[[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_j=1"
diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c
index 7e272e2..68d5c86 100644
--- a/kpatch-build/kpatch-elf.c
+++ b/kpatch-build/kpatch-elf.c
@@ -325,7 +325,7 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf)
list_for_each_entry(sym, &kelf->symbols, list) {
if (sym->type != STT_FUNC || !sym->sec || !sym->sec->rela)
continue;
-#ifdef __powerpc64__
+#if defined(__powerpc64__) || defined(__aarch64__)
list_for_each_entry(rela, &sym->sec->rela->relas, list) {
if (!strcmp(rela->sym->name, "_mcount")) {
sym->has_func_profiling = 1;
--
2.23.0

View File

@ -1,112 +0,0 @@
From 0de9a5da0cc278973caabfb9929dc58514c73639 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 20 Dec 2018 04:55:38 +0000
Subject: [PATCH 01/23] support compile kpatch on aarch64
delete __x86_64__ to support compile kpatch on aarch64.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/Makefile | 4 ++++
kpatch-build/create-diff-object.c | 14 +-------------
2 files changed, 5 insertions(+), 13 deletions(-)
diff --git a/kpatch-build/Makefile b/kpatch-build/Makefile
index 7505e07..8efae94 100644
--- a/kpatch-build/Makefile
+++ b/kpatch-build/Makefile
@@ -14,6 +14,10 @@ ifeq ($(ARCH),x86_64)
SOURCES += insn/insn.c insn/inat.c
INSN = insn/insn.o insn/inat.o
insn/%.o: CFLAGS := $(filter-out -Wconversion, $(CFLAGS))
+else ifeq ($(ARCH),aarch64)
+SOURCES += insn/insn.c insn/inat.c
+INSN = insn/insn.o insn/inat.o
+insn/%.o: CFLAGS := $(filter-out -Wconversion, $(CFLAGS))
else ifeq ($(ARCH),ppc64le)
SOURCES += gcc-plugins/ppc64le-plugin.c
PLUGIN = gcc-plugins/ppc64le-plugin.so
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index aedd07d..2707cdb 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -475,7 +475,6 @@ out:
log_debug("section %s has changed\n", sec->name);
}
-#ifdef __x86_64__
/*
* Determine if a section has changed only due to a WARN* or might_sleep
* macro call's embedding of the line number into an instruction operand.
@@ -586,7 +585,7 @@ static int kpatch_line_macro_change_only(struct section *sec)
return 1;
}
-#elif __powerpc64__
+#if __powerpc64__
#define PPC_INSTR_LEN 4
#define PPC_RA_OFFSET 16
@@ -652,11 +651,6 @@ static int kpatch_line_macro_change_only(struct section *sec)
return 1;
}
-#else
-static int kpatch_line_macro_change_only(struct section *sec)
-{
- return 0;
-}
#endif
static void kpatch_compare_sections(struct list_head *seclist)
@@ -1215,7 +1209,6 @@ static void kpatch_compare_correlated_elements(struct kpatch_elf *kelf)
kpatch_compare_symbols(&kelf->symbols);
}
-#ifdef __x86_64__
static void rela_insn(const struct section *sec, const struct rela *rela,
struct insn *insn)
{
@@ -1239,7 +1232,6 @@ static void rela_insn(const struct section *sec, const struct rela *rela,
return;
}
}
-#endif
static bool is_callback_section(struct section *sec) {
@@ -1785,7 +1777,6 @@ static int jump_table_group_size(struct kpatch_elf *kelf, int offset)
return size;
}
-#ifdef __x86_64__
static int parainstructions_group_size(struct kpatch_elf *kelf, int offset)
{
static int size = 0;
@@ -1820,7 +1811,6 @@ static int smp_locks_group_size(struct kpatch_elf *kelf, int offset)
{
return 4;
}
-#endif
#ifdef __powerpc64__
static int fixup_entry_group_size(struct kpatch_elf *kelf, int offset)
{
@@ -1915,7 +1905,6 @@ static struct special_section special_sections[] = {
.name = "__jump_table",
.group_size = jump_table_group_size,
},
-#ifdef __x86_64__
{
.name = ".smp_locks",
.group_size = smp_locks_group_size,
@@ -1928,7 +1917,6 @@ static struct special_section special_sections[] = {
.name = ".altinstructions",
.group_size = altinstructions_group_size,
},
-#endif
#ifdef __powerpc64__
{
.name = "__ftr_fixup",
--
2.18.1

View File

@ -0,0 +1,31 @@
From 72d28d667f8f6baa88882abfc1590cce3e9e2b1f Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Sun, 14 Nov 2021 15:57:55 +0800
Subject: [PATCH 02/24] create-diff-object: fix symbol changed sections error
on aarch64
$d is reserved symbols in aarch64, we met following error when
building patch on aarch64. just ignore it.
ERROR: cmdline.o: symbol changed sections: $d
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index ca55180..6c28280 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -865,6 +865,8 @@ static void kpatch_compare_correlated_symbol(struct symbol *sym)
if ((sym2->sec->twin && sym2->sec->twin->ignore) ||
kpatch_subsection_changed(sym1->sec, sym2->sec))
sym->status = CHANGED;
+ else if (sym1->name[0] == '$') /* reserved symbols in aarch64 */
+ log_debug("maping symbols: %s", sym1->name); /* do nothing just ignogre */
else
DIFF_FATAL("symbol changed sections: %s", sym1->name);
}
--
2.23.0

View File

@ -1,744 +0,0 @@
From d3665b019100715e41b75493d31d51d602ca056a Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 07:09:50 -0500
Subject: [PATCH 02/23] kpatch-build: support build patch for aarch64
use R_AARCH64_ABS64 for aarch64
exclude line only change for arm64 by compare mov instruction
except immediate part.
add find_special_section_data_arm64 for arm64:
arm64 kernel have no paravirt_patch_site or orc_entry structure
in vmlinux, we don't need to check these two struct for arm64.
support cross compile for aarch64
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 276 ++++++++++++++++++++++------
kpatch-build/create-kpatch-module.c | 25 ++-
kpatch-build/kpatch-build | 116 +++++++++++-
kpatch-build/kpatch-gcc | 4 +-
4 files changed, 352 insertions(+), 69 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 2707cdb..b161fee 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -76,6 +76,32 @@ enum subsection {
enum loglevel loglevel = NORMAL;
+#ifndef EM_X86_64
+#define EM_X86_64 62
+#endif
+
+#ifndef EM_AARCH64
+#define EM_AARCH64 183
+#endif
+
+#ifndef R_AARCH64_ABS64
+#define R_AARCH64_NONE 0
+#define R_AARCH64_ABS64 257
+#define R_AARCH64_CALL26 283
+#endif
+
+static unsigned int arch;
+static unsigned int absolute_rela_type;
+
+static unsigned int arch_of_elf(Elf *elf)
+{
+ GElf_Ehdr eh;
+
+ if (!gelf_getehdr(elf, &eh))
+ ERROR("gelf_getehdr");
+ return eh.e_machine;
+}
+
/*******************
* Data structures
* ****************/
@@ -652,6 +678,67 @@ static int kpatch_line_macro_change_only(struct section *sec)
return 1;
}
#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)
{
@@ -667,7 +754,16 @@ 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;
@@ -727,6 +823,8 @@ static void kpatch_compare_correlated_symbol(struct symbol *sym)
if ((sym2->sec->twin && sym2->sec->twin->ignore) ||
kpatch_subsection_changed(sym1->sec, sym2->sec))
sym->status = CHANGED;
+ else if (sym1->name[0] == '$') /* reserved symbols in aarch64 */
+ log_debug("maping symbols: %s", sym1->name); /* do nothing just ignogre */
else
DIFF_FATAL("symbol changed sections: %s", sym1->name);
}
@@ -1302,22 +1400,22 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
continue;
}
-#ifdef __powerpc64__
add_off = 0;
-#else
- if (rela->type == R_X86_64_PC32 ||
- rela->type == R_X86_64_PLT32) {
- struct insn insn;
- rela_insn(sec, rela, &insn);
- add_off = (unsigned int)((long)insn.next_byte -
- (long)sec->base->data->d_buf -
- rela->offset);
- } else if (rela->type == R_X86_64_64 ||
- rela->type == R_X86_64_32S)
- add_off = 0;
- else
- continue;
-#endif
+ if (arch == EM_X86_64) {
+ if (rela->type == R_X86_64_PC32 ||
+ rela->type == R_X86_64_PLT32) {
+ struct insn insn;
+
+ rela_insn(sec, rela, &insn);
+ add_off = (unsigned int)((long)insn.next_byte -
+ (long)sec->base->data->d_buf -
+ rela->offset);
+ } else if (rela->type == R_X86_64_64 ||
+ rela->type == R_X86_64_32S)
+ add_off = 0;
+ else
+ continue;
+ }
/*
* Attempt to replace references to unbundled sections
@@ -2415,7 +2513,7 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj
/* entries[index].sec */
ALLOC_LINK(rela, &karch_sec->rela->relas);
rela->sym = sec->secsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = 0;
rela->offset = (unsigned int)(index * sizeof(struct kpatch_arch) + \
offsetof(struct kpatch_arch, sec));
@@ -2423,7 +2521,7 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj
/* entries[index].objname */
ALLOC_LINK(rela, &karch_sec->rela->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = offset_of_string(&kelf->strings, objname);
rela->offset = (unsigned int)(index * sizeof(struct kpatch_arch) + \
offsetof(struct kpatch_arch, objname));
@@ -2622,7 +2720,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = sym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = 0;
rela->offset = (unsigned int)(index * sizeof(*funcs));
@@ -2632,7 +2730,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = offset_of_string(&kelf->strings, sym->name);
rela->offset = (unsigned int)(index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func, name));
@@ -2643,7 +2741,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = (unsigned int)(index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func,objname));
@@ -2701,7 +2799,10 @@ static int function_ptr_rela(const struct rela *rela)
rela_toc->addend == (int)rela_toc->sym->sym.st_value &&
(rela->type == R_X86_64_32S ||
rela->type == R_PPC64_TOC16_HA ||
- rela->type == R_PPC64_TOC16_LO_DS));
+ rela->type == R_PPC64_TOC16_LO_DS ||
+ rela->type == R_AARCH64_ADR_PREL_PG_HI21 ||
+ rela->type == R_AARCH64_ADD_ABS_LO12_NC));
+
}
static int may_need_dynrela(const struct rela *rela)
@@ -2955,7 +3056,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in ksyms[index].name field */
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, rela->sym->name);
rela2->offset = (unsigned int)(index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, name));
@@ -2963,7 +3064,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in ksyms[index].objname field */
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, sym_objname);
rela2->offset = (unsigned int)(index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, objname));
@@ -2984,7 +3085,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
ERROR("can't create dynrela for section %s (symbol %s): no bundled or section symbol",
sec->name, rela->sym->name);
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = rela->offset;
rela2->offset = (unsigned int)(index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, dest));
@@ -2992,7 +3093,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in krelas[index].objname field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, objname);
rela2->offset = (unsigned int)(index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, objname));
@@ -3000,7 +3101,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in krelas[index].ksym field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
rela2->sym = ksym_sec_sym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = (unsigned int)(index * sizeof(*ksyms));
rela2->offset = (unsigned int)(index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, ksym));
@@ -3063,7 +3164,7 @@ static void kpatch_create_callbacks_objname_rela(struct kpatch_elf *kelf, char *
if (!strcmp(callbackp->name, sec->name)) {
ALLOC_LINK(rela, &sec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = callbackp->offset;
break;
@@ -3116,40 +3215,79 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
/* add rela in .rela__mcount_loc to fill in function pointer */
ALLOC_LINK(rela, &relasec->relas);
rela->sym = sym;
- rela->type = R_X86_64_64;
- rela->addend = 0;
- rela->offset = (unsigned int)(index * sizeof(void*));
+ if (arch == EM_X86_64) {
+ rela->type = R_X86_64_64;
+ rela->addend = 0;
+ rela->offset = (unsigned int)(index * sizeof(void *));
- /*
- * Modify the first instruction of the function to "callq
- * __fentry__" so that ftrace will be happy.
- */
- newdata = malloc(sym->sec->data->d_size);
- if (!newdata)
- ERROR("malloc");
+ /*
+ * Modify the first instruction of the function to "callq
+ * __fentry__" so that ftrace will be happy.
+ */
+ newdata = malloc(sym->sec->data->d_size);
+ if (!newdata)
+ ERROR("malloc");
- memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
- sym->sec->data->d_buf = newdata;
- insn = newdata;
+ memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
+ sym->sec->data->d_buf = newdata;
+ insn = newdata;
- rela = list_first_entry(&sym->sec->rela->relas, struct rela,
+ rela = list_first_entry(&sym->sec->rela->relas, struct rela,
list);
- /*
- * R_X86_64_NONE is only generated by older versions of kernel/gcc
- * which use the mcount script.
- */
- if (rela->type == R_X86_64_NONE) {
- if (insn[0] != 0xf)
+ /*
+ * R_X86_64_NONE is only generated by older versions of kernel/gcc
+ * which use the mcount script.
+ */
+ if (rela->type == R_X86_64_NONE) {
+ if (insn[0] != 0xf)
+ ERROR("%s: unexpected instruction at the start of the function",
+ sym->name);
+ insn[0] = 0xe8;
+ insn[1] = 0;
+ insn[2] = 0;
+ insn[3] = 0;
+ insn[4] = 0;
+
+ rela->type = R_X86_64_PC32;
+ }
+ } else if (arch == EM_AARCH64) {
+ unsigned int *insnp;
+
+ rela->type = R_AARCH64_ABS64;
+ /* bl <__fentry__> is the second insn */
+ rela->addend = 4;
+ rela->offset = (unsigned int)(index * sizeof(void *));
+
+ newdata = malloc(sym->sec->data->d_size);
+ if (!newdata)
+ ERROR("malloc");
+
+ memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
+ sym->sec->data->d_buf = newdata;
+ insnp = newdata;
+
+ /*
+ * mov x9, x30
+ * nop //function in .text.<func>, so it be replaced with nop by
+ * recordmcount
+ *
+ * mov x30, x9
+ */
+ if (insnp[0] != 0xaa1e03e9 || insnp[1] != 0xd503201f
+ || insnp[2] != 0xaa0903fe)
ERROR("%s: unexpected instruction at the start of the function",
- sym->name);
- insn[0] = 0xe8;
- insn[1] = 0;
- insn[2] = 0;
- insn[3] = 0;
- insn[4] = 0;
-
- rela->type = R_X86_64_PC32;
+ sym->name);
+
+ /* change the nop to bl __fentry__ */
+ insnp[1] = 0x94000000;
+ rela = list_first_entry(&sym->sec->rela->relas, struct rela,
+ list);
+ rela->type = R_AARCH64_CALL26;
+ rela->offset = 4;
+
+ } else {
+ ERROR("unsupport arch %d\n", arch);
}
index++;
@@ -3349,6 +3489,8 @@ int main(int argc, char *argv[])
char *hint = NULL, *orig_obj, *patched_obj, *parent_name;
char *parent_symtab, *mod_symvers, *patch_name, *output_obj;
struct sym_compare_type *base_locals, *sym_comp;
+ char *no_profiling_calls = NULL;
+ char *gcc_add_option = NULL, *mlongcall = NULL;
arguments.debug = 0;
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -3369,6 +3511,13 @@ int main(int argc, char *argv[])
kelf_base = kpatch_elf_open(orig_obj);
kelf_patched = kpatch_elf_open(patched_obj);
+ arch = arch_of_elf(kelf_base->elf);
+ if (arch == EM_X86_64)
+ absolute_rela_type = R_X86_64_64;
+ else if (arch == EM_AARCH64)
+ absolute_rela_type = R_AARCH64_ABS64;
+ else
+ ERROR("only arch x86_64 and arm64 be supported\n");
kpatch_compare_elf_headers(kelf_base->elf, kelf_patched->elf);
kpatch_check_program_headers(kelf_base->elf);
@@ -3407,7 +3556,12 @@ int main(int argc, char *argv[])
*/
kpatch_mark_ignored_sections(kelf_patched);
kpatch_compare_correlated_elements(kelf_patched);
- kpatch_check_func_profiling_calls(kelf_patched);
+ no_profiling_calls = getenv("NO_PROFILING_CALLS");
+ if (!no_profiling_calls)
+ kpatch_check_func_profiling_calls(kelf_patched);
+ else
+ log_debug("NO_PROFILING_CALLS set\n");
+
kpatch_elf_teardown(kelf_base);
kpatch_elf_free(kelf_base);
@@ -3467,7 +3621,13 @@ int main(int argc, char *argv[])
kpatch_create_callbacks_objname_rela(kelf_out, parent_name);
kpatch_build_strings_section_data(kelf_out);
- kpatch_create_mcount_sections(kelf_out);
+ gcc_add_option = getenv("GCC_ADD_OPTION");
+ if (gcc_add_option)
+ mlongcall = strstr(gcc_add_option, "-mlong-calls");
+ if (arch == EM_AARCH64 && mlongcall)
+ printf("-mlong-calls found, no need to create mcount section\n");
+ else
+ kpatch_create_mcount_sections(kelf_out);
/*
* At this point, the set of output sections and symbols is
diff --git a/kpatch-build/create-kpatch-module.c b/kpatch-build/create-kpatch-module.c
index 3d197a7..e8a235d 100644
--- a/kpatch-build/create-kpatch-module.c
+++ b/kpatch-build/create-kpatch-module.c
@@ -31,6 +31,18 @@
char *childobj;
enum loglevel loglevel = NORMAL;
+static unsigned int arch;
+static unsigned int absolute_rela_type;
+
+static unsigned int arch_of_elf(Elf *elf)
+{
+ GElf_Ehdr eh;
+
+ if (!gelf_getehdr(elf, &eh))
+ ERROR("gelf_getehdr");
+ return eh.e_machine;
+}
+
/*
* Create .kpatch.dynrelas from .kpatch.relocations and .kpatch.symbols sections
*
@@ -102,14 +114,14 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
/* dest */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = sym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = dest_offset;
rela->offset = (unsigned int)(index * sizeof(*dynrelas));
/* name */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = strsec->secsym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = name_offset;
rela->offset = (unsigned int)(index * sizeof(*dynrelas) + \
offsetof(struct kpatch_patch_dynrela, name));
@@ -117,7 +129,7 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
/* objname */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = strsec->secsym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = (unsigned int)(index * sizeof(*dynrelas) + \
offsetof(struct kpatch_patch_dynrela, objname));
@@ -200,6 +212,13 @@ int main(int argc, char *argv[])
childobj = basename(arguments.args[0]);
kelf = kpatch_elf_open(arguments.args[0]);
+ arch = arch_of_elf(kelf->elf);
+ if (arch == EM_X86_64)
+ absolute_rela_type = R_X86_64_64;
+ else if (arch == EM_AARCH64)
+ absolute_rela_type = R_AARCH64_ABS64;
+ else
+ ERROR("only arch x86_64 and arm64 be supported\n");
/*
* Sanity checks:
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index ae0733c..17a5e11 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -299,12 +299,72 @@ find_special_section_data_ppc64le() {
return
}
+find_special_section_data_arm64() {
+
+ [[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_j=1"
+
+ # If $AWK_OPTIONS are blank gawk would treat "" as a blank script
+ # shellcheck disable=SC2086
+ SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
+ gawk --non-decimal-data $AWK_OPTIONS '
+ BEGIN { a = b = e = j = c = f = s = i = r = t = h = 0 }
+
+ # Set state if name matches
+ a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
+ b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
+ e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
+ j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
+ c == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {c = 1; next}
+ t == 0 && /DW_AT_name.* klp_object[[:space:]]*$/ {t = 1; next}
+
+ # Reset state unless this abbrev describes the struct size
+ a == 1 && !/DW_AT_byte_size/ { a = 0; next }
+ b == 1 && !/DW_AT_byte_size/ { b = 0; next }
+ e == 1 && !/DW_AT_byte_size/ { e = 0; next }
+ j == 1 && !/DW_AT_byte_size/ { j = 0; next }
+ c == 1 && /DW_TAG_structure_type/ { c = 3; next }
+ t == 1 && /DW_TAG_structure_type/ { t = 3; next }
+ c == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
+ c == 1 && /DW_AT_name.* old_sympos[[:space:]]*$/ {s = 2; next}
+ i == 1 && /DW_AT_name.* immediate[[:space:]]*$/ {i = 2; next}
+ t == 1 && /DW_AT_name.* relocs[[:space:]]*$/ {r = 2; next}
+ t == 1 && /DW_AT_name.* hooks_load[[:space:]]*$/ {h = 2; next}
+
+ # Now that we know the size, stop parsing for it
+ a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
+ b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2}
+ e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
+ j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
+ f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
+ s == 2 {printf("export KLP_SUPPORT_OLD_SYMPOS=y\n"); s = 3}
+ i == 2 {printf("export KLP_SUPPORT_IMMEDIATE=y\n"); i = 3}
+ r == 2 {printf("export KLP_SUPPORT_RELOCS=y\n"); r = 3}
+ h == 2 {printf("export KLP_SUPPORT_LOADHOOKS=y\n"); h = 3}
+
+ # Bail out once we have everything
+ a == 2 && b == 2 && e == 2 && (j == 2 || skip_j) && c == 3 && t == 3 {exit}')"
+
+ [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
+
+ [[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
+ [[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
+ [[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct exception_table_entry size"
+ [[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]] && die "can't find special struct jump_entry size"
+
+ return
+}
+
find_special_section_data() {
if [[ "$ARCH" = "ppc64le" ]]; then
find_special_section_data_ppc64le
return
fi
+ if [[ "$ARCH" = "arm64" ]]; then
+ find_special_section_data_arm64
+ return
+ fi
+
[[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
[[ "$CONFIG_UNWINDER_ORC" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_o=1"
[[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_j=1"
@@ -428,6 +488,29 @@ find_kobj() {
done
}
+arch_export() {
+ E_MACHINE=$(od -An -j18 -N2 -d $VMLINUX)
+ if [[ $E_MACHINE -eq 62 ]]; then
+ export ARCH=x86_64
+ export ARCH_COMPILE=
+ export ENDIAN=little
+ export GCC_ADD_OPTION=
+ elif [[ $E_MACHINE -eq 183 ]]; then
+ export ARCH=arm64
+ if [ $(arch) != "aarch64" ]; then
+ export ARCH_COMPILE=aarch64-linux-gnu-
+ fi
+ export ENDIAN=little
+ if grep "\-mlong-calls" /lib/modules/$ARCHVERSION/build//Makefile > /dev/null; then
+ export GCC_ADD_OPTION="-fno-section-anchors -mlong-calls"
+ else
+ export GCC_ADD_OPTION="-fno-section-anchors"
+ fi
+ else
+ die "only support arm64 or x86_64 architecture"
+ fi
+}
+
# Only allow alphanumerics and '_' and '-' in the module name. Everything else
# is replaced with '-'. Also truncate to 48 chars so the full name fits in the
# kernel's 56-byte module name array.
@@ -786,13 +869,13 @@ apply_patches
remove_patches
cp -LR "$DATADIR/patch" "$TEMPDIR" || die
-
+arch_export
if [[ "$ARCH" = "ppc64le" ]]; then
ARCH_KCFLAGS="-mcmodel=large -fplugin=$PLUGINDIR/ppc64le-plugin.so"
fi
export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections \
- $ARCH_KCFLAGS $DEBUG_KCFLAGS"
+ $ARCH_KCFLAGS $DEBUG_KCFLAGS ${GCC_ADD_OPTION}"
echo "Reading special section data"
find_special_section_data
@@ -806,7 +889,7 @@ echo "Building original source"
unset KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
+CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make "-j$CPUS" $TARGETS 2>&1 | logger || die
echo "Building patched source"
apply_patches
@@ -817,7 +900,7 @@ KPATCH_GCC_SRCDIR="$SRCDIR"
export KPATCH_GCC_SRCDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
+CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
KBUILD_MODPOST_WARN=1 \
make "-j$CPUS" $TARGETS 2>&1 | logger || die
@@ -950,6 +1033,26 @@ if "$KPATCH_MODULE"; then
export KCPPFLAGS="-D__KPATCH_MODULE__"
fi
+if [[ -n "$KLP_SUPPORT_FORCE" ]];then
+ export KCPPFLAGS="-D__KLP_SUPPORT_FORCE__ $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_OLD_SYMPOS" ]];then
+ export KCPPFLAGS="-DHAVE_SYMPOS $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_IMMEDIATE" ]];then
+ export KCPPFLAGS="-DHAVE_IMMEDIATE $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_RELOCS" ]];then
+ export KCPPFLAGS="-DHAVE_ELF_RELOCS $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_LOADHOOKS" ]];then
+ export KCPPFLAGS="-DHAVE_LOADHOOKS $KCPPFLAGS"
+fi
+
echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
@@ -962,12 +1065,12 @@ fi
cd "$TEMPDIR/output" || die
# $KPATCH_LDFLAGS and result of find used as list, no quotes.
# shellcheck disable=SC2086,SC2046
-ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die
+${ARCH_COMPILE}ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die
if "$KPATCH_MODULE"; then
# Add .kpatch.checksum for kpatch script
md5sum ../patch/tmp_output.o | awk '{printf "%s\0", $1}' > checksum.tmp || die
- objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly ../patch/tmp_output.o || die
+ ${ARCH_COMPILE}objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly ../patch/tmp_output.o || die
rm -f checksum.tmp
"$TOOLSDIR"/create-kpatch-module "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o 2>&1 | logger 1
check_pipe_status create-kpatch-module
@@ -984,6 +1087,7 @@ fi
KPATCH_BUILD="$KPATCH_BUILD" KPATCH_NAME="$MODNAME" \
KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
+CROSS_COMPILE="$ARCH_COMPILE" \
make 2>&1 | logger || die
if ! "$KPATCH_MODULE"; then
diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc
index 9663290..35d7c1c 100755
--- a/kpatch-build/kpatch-gcc
+++ b/kpatch-build/kpatch-gcc
@@ -13,7 +13,7 @@ fi
declare -a args=("$@")
-if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then
+if [[ "$TOOLCHAINCMD" =~ "${ARCH_COMPILE}gcc" ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
@@ -60,7 +60,7 @@ if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then
fi
shift
done
-elif [[ "$TOOLCHAINCMD" = "ld" ]] ; then
+elif [[ "$TOOLCHAINCMD" = "${ARCH_COMPILE}ld" ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
--
2.18.1

View File

@ -0,0 +1,90 @@
From b71b6e5f46fdc3f1b709b58777cb0da7ec9fc008 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
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 <xiezhipeng1@huawei.com>
---
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

View File

@ -0,0 +1,43 @@
From f82f5ff61b8087e203a994da3911a1c5f3dee978 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Sun, 14 Nov 2021 19:53:22 +0800
Subject: [PATCH 04/24] create-diff-object:support skip check func profiling
calls
when kernel support livepatch without ftrace, we can skip check
func profiling calls.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index c20f75e..7247345 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -3773,6 +3773,7 @@ int main(int argc, char *argv[])
struct section *sec, *symtab;
char *orig_obj, *patched_obj, *parent_name;
char *parent_symtab, *mod_symvers, *patch_name, *output_obj;
+ char *no_profiling_calls = NULL;
memset(&arguments, 0, sizeof(arguments));
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -3824,7 +3825,12 @@ int main(int argc, char *argv[])
kpatch_compare_correlated_elements(kelf_patched);
kpatch_mark_ignored_functions_same(kelf_patched);
kpatch_mark_ignored_sections_same(kelf_patched);
- kpatch_check_func_profiling_calls(kelf_patched);
+ no_profiling_calls = getenv("NO_PROFILING_CALLS");
+ if (!no_profiling_calls)
+ kpatch_check_func_profiling_calls(kelf_patched);
+ else
+ log_debug("NO_PROFILING_CALLS set\n");
+
kpatch_elf_teardown(kelf_orig);
kpatch_elf_free(kelf_orig);
--
2.23.0

View File

@ -1,32 +0,0 @@
From 67c3fb57cf0b991c4f70aec78bdf25a47fb590b4 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:42 +0000
Subject: [PATCH 04/23] livepatch, fix: use THIS modname as the name of
ddebug_table
We just want a unique name for every module, so put a _ddebug in
this file as the first of _ddebug array. Then remove path will work
correctly, use the mod->name.
Suggested-by: Li Bin <huawei.libin@huawei.com>
Signed-off-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index e12fd50..6ae40de 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -473,6 +473,7 @@ out:
static void __exit patch_exit(void)
{
+ pr_debug("make THIS modname first\n");
#ifndef HAVE_SIMPLE_ENABLE
WARN_ON(klp_unregister_patch(lpatch));
#endif
--
2.18.1

View File

@ -1,7 +1,7 @@
From 232f97ae9acb73ad7bb0b974f6a94ae4c4ca03d9 Mon Sep 17 00:00:00 2001 From fb93c5a8dfbc035ade8fc40b75b85018afaeed2e Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Tue, 25 Feb 2020 22:44:50 -0500 Date: Tue, 25 Feb 2020 22:44:50 -0500
Subject: [PATCH 03/23] create-diff-object: new static var should be included Subject: [PATCH 05/24] create-diff-object: new static var should be included
Before this patch, only global variables(no referenced) will be Before this patch, only global variables(no referenced) will be
included by kpatch-build. But some macros put some static varibles included by kpatch-build. But some macros put some static varibles
@ -18,10 +18,10 @@ Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
1 file changed, 16 insertions(+) 1 file changed, 16 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index b161fee..b94060e 100644 index 7247345..1be4fac 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -1704,6 +1704,21 @@ static void kpatch_include_force_elements(struct kpatch_elf *kelf) @@ -1909,6 +1909,21 @@ static void kpatch_include_force_elements(struct kpatch_elf *kelf)
sym->include = 0; sym->include = 0;
} }
@ -43,14 +43,14 @@ index b161fee..b94060e 100644
static int kpatch_include_new_globals(struct kpatch_elf *kelf) static int kpatch_include_new_globals(struct kpatch_elf *kelf)
{ {
struct symbol *sym; struct symbol *sym;
@@ -3573,6 +3588,7 @@ int main(int argc, char *argv[]) @@ -3839,6 +3854,7 @@ int main(int argc, char *argv[])
callbacks_exist = kpatch_include_callback_elements(kelf_patched); callbacks_exist = kpatch_include_callback_elements(kelf_patched);
kpatch_include_force_elements(kelf_patched); kpatch_include_force_elements(kelf_patched);
new_globals_exist = kpatch_include_new_globals(kelf_patched); new_globals_exist = kpatch_include_new_globals(kelf_patched);
+ kpatch_include_new_static_var(kelf_patched); + kpatch_include_new_static_var(kelf_patched);
kpatch_include_debug_sections(kelf_patched); kpatch_include_debug_sections(kelf_patched);
kpatch_process_special_sections(kelf_patched); kpatch_process_special_sections(kelf_patched, lookup);
-- --
2.18.1 2.23.0

View File

@ -1,31 +0,0 @@
From 30446d9a1a65c8369a54844d471c2aeb4c9139dd Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:58 +0000
Subject: [PATCH 06/23] create-diff-object: don't create dynamic reloc for
symbol exported by patch itself
when a patch export a new function, ___kcrctab+xxx has a reloc,
use origin reloc to get right symbol version.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 3681adb..ba2976b 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -3056,6 +3056,9 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
if (!strcmp(sym_objname, "vmlinux"))
continue;
+ if (!strcmp(sym_objname, objname))
+ continue;
+
external = 1;
}
}
--
2.18.1

View File

@ -1,7 +1,7 @@
From 24c01beb0ac8cee521ba654ece6c22f6ce9bdafe Mon Sep 17 00:00:00 2001 From 80b74891e1d609d7881f9c9d29fe4828c49e2d83 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:51 +0000 Date: Fri, 2 Nov 2018 17:24:51 +0000
Subject: [PATCH 05/23] create-diff-object: fix correlate static local Subject: [PATCH 06/24] create-diff-object: fix correlate static local
variables for __param section variables for __param section
kpatch-build correlate fail when no sections reference kpatch-build correlate fail when no sections reference
@ -31,20 +31,20 @@ Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
1 file changed, 4 insertions(+) 1 file changed, 4 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index b94060e..3681adb 100644 index 1be4fac..7efe7b4 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -1108,6 +1108,10 @@ static int kpatch_is_normal_static_local(struct symbol *sym) @@ -1277,6 +1277,10 @@ static bool kpatch_is_normal_static_local(struct symbol *sym)
if (is_special_static(sym)) if (is_special_static(sym))
return 0; return false;
+ if (!strncmp(sym->name, "__param_", strlen("__param_")) && + if (!strncmp(sym->name, "__param_", strlen("__param_")) &&
+ !strncmp(sym->sec->name, "__param", strlen("__param"))) + !strncmp(sym->sec->name, "__param", strlen("__param")))
+ return 0; + return false;
+ +
return 1; return true;
} }
-- --
2.18.1 2.23.0

View File

@ -1,71 +0,0 @@
From 66d1b112903b4942cc1033a1be93ae79c1ecf8ef Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
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 <xiezhipeng1@huawei.com>
Tested-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Li Bin <huawei.libin@huawei.com>
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
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

View File

@ -1,7 +1,7 @@
From 9f30a27617915ee8c59aa43d9165d938129796b3 Mon Sep 17 00:00:00 2001 From 42cfc6a9add67e23433bf431da74d6babe38be61 Mon Sep 17 00:00:00 2001
From: Zhiyu Hu <huzhiyu1@huawei.com> From: Zhiyu Hu <huzhiyu1@huawei.com>
Date: Fri, 28 Dec 2018 07:06:38 +0000 Date: Fri, 28 Dec 2018 07:06:38 +0000
Subject: [PATCH 08/23] fix rodata.str problem Subject: [PATCH 07/24] fix rodata.str problem
fix some rodata.str problem fix some rodata.str problem
@ -11,10 +11,10 @@ Signed-off-by: Zhiyu Hu <huzhiyu1@huawei.com>
1 file changed, 1 insertion(+), 1 deletion(-) 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 8ce3b59..f37d404 100644 index 7efe7b4..18aff6d 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -1634,7 +1634,7 @@ static void kpatch_include_standard_elements(struct kpatch_elf *kelf) @@ -1838,7 +1838,7 @@ static void kpatch_include_standard_elements(struct kpatch_elf *kelf)
!strcmp(sec->name, ".toc") || !strcmp(sec->name, ".toc") ||
!strcmp(sec->name, ".rodata") || !strcmp(sec->name, ".rodata") ||
(!strncmp(sec->name, ".rodata.", 8) && (!strncmp(sec->name, ".rodata.", 8) &&
@ -24,5 +24,5 @@ index 8ce3b59..f37d404 100644
} }
} }
-- --
2.18.1 2.23.0

View File

@ -1,22 +1,22 @@
From 1bc8c76085839576576fc780336fbd9d7ebd29ef Mon Sep 17 00:00:00 2001 From 3d3cb8c0b294a60faaeb68e0d7361babdc1b8902 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Tue, 25 Feb 2020 23:40:37 -0500 Date: Tue, 25 Feb 2020 23:40:37 -0500
Subject: [PATCH 09/23] livepatch-patch-hook: don't active patch when insmod Subject: [PATCH 08/24] livepatch-patch-hook: support no active after load
Don't active patch after loading the patch when suppport Don't active patch after loading the patch when
DISABLE_AFTER_LOAD is set. DISABLE_AFTER_LOAD is set.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com> Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
--- ---
kmod/patch/livepatch-patch-hook.c | 2 ++ kmod/patch/livepatch-patch-hook.c | 2 ++
kpatch-build/kpatch-build | 4 ++++ kpatch-build/kpatch-build | 5 +++++
2 files changed, 6 insertions(+) 2 files changed, 7 insertions(+)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index 6ae40de..fb23a94 100644 index 3d13ab9..b578ef3 100644
--- a/kmod/patch/livepatch-patch-hook.c --- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c +++ b/kmod/patch/livepatch-patch-hook.c
@@ -455,6 +455,7 @@ static int __init patch_init(void) @@ -576,6 +576,7 @@ static int __init patch_init(void)
} }
#endif #endif
@ -24,7 +24,7 @@ index 6ae40de..fb23a94 100644
ret = klp_enable_patch(lpatch); ret = klp_enable_patch(lpatch);
if (ret) { if (ret) {
#ifndef HAVE_SIMPLE_ENABLE #ifndef HAVE_SIMPLE_ENABLE
@@ -463,6 +464,7 @@ static int __init patch_init(void) @@ -584,6 +585,7 @@ static int __init patch_init(void)
patch_free_livepatch(lpatch); patch_free_livepatch(lpatch);
return ret; return ret;
} }
@ -33,20 +33,21 @@ index 6ae40de..fb23a94 100644
return 0; return 0;
out: out:
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 17a5e11..894f0ab 100755 index ad3a079..c85e05a 100755
--- a/kpatch-build/kpatch-build --- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build
@@ -1053,6 +1053,10 @@ if [[ -n "$KLP_SUPPORT_LOADHOOKS" ]];then @@ -1176,6 +1176,11 @@ export KCFLAGS="-I$DATADIR/patch $ARCH_KCFLAGS"
export KCPPFLAGS="-DHAVE_LOADHOOKS $KCPPFLAGS" if [[ "$USE_KLP" -eq 0 ]]; then
export KCPPFLAGS="-D__KPATCH_MODULE__"
fi fi
+
+if [[ -n "$DISABLE_AFTER_LOAD" ]];then +if [[ -n "$DISABLE_AFTER_LOAD" ]];then
+ export KCPPFLAGS="-DDISABLE_AFTER_LOAD $KCPPFLAGS" + export KCPPFLAGS="-DDISABLE_AFTER_LOAD $KCPPFLAGS"
+fi +fi
+ +
save_env
echo "Building patch module: $MODNAME.ko" echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
-- --
2.18.1 2.23.0

View File

@ -0,0 +1,198 @@
From 12530d7f476e8629fc7e50443f34164a43ef18b6 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 06:44:06 -0500
Subject: [PATCH 09/24] kpatch-build: enhance for out of tree module
support set USERMODBUILDDIR to build patch for out
of tree module.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 62 +++++++++++++++++++++++++++++++--------
kpatch-build/kpatch-cc | 4 ++-
2 files changed, 53 insertions(+), 13 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index c85e05a..3aca1f3 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -492,7 +492,11 @@ filter_parent_obj()
local dir="${1}"
local file="${2}"
- grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd"
+ grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd" | while read input; do
+ if [ "$(readlink -f $input)" != "$(readlink -f ${dir}/.${file}.cmd)" ];then
+ echo $input;
+ fi
+ done
}
find_parent_obj() {
@@ -514,6 +518,11 @@ find_parent_obj() {
num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | wc -l)"
[[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
fi
+ if [[ "$num" -eq 0 ]]; then
+ parent="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | head -n1)"
+ num="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
+ [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
+ fi
else
parent="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | head -n1)"
num="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | wc -l)"
@@ -703,6 +712,10 @@ if [[ -n "$SRCRPM" ]]; then
ARCHVERSION="${ARCHVERSION#alt-}"
fi
+if [[ -n "$USERMODBUILDDIR" ]]; then
+ OOT_MODULE="yes"
+fi
+
if [[ -n "$OOT_MODULE" ]] && [[ -z "$USERSRCDIR" ]]; then
warn "--oot-module requires --sourcedir"
exit 1
@@ -720,7 +733,7 @@ if [[ -n "$USERSRCDIR" ]]; then
fi
SRCDIR="$USERSRCDIR"
- if [[ -z "$OOT_MODULE" ]]; then
+ if [[ -z "$OOT_MODULE" || "$OOT_MODULE" == "yes" ]]; then
[[ -z "$VMLINUX" ]] && VMLINUX="$SRCDIR"/vmlinux
[[ ! -e "$VMLINUX" ]] && die "can't find vmlinux"
@@ -742,7 +755,7 @@ if [[ "$ARCHVERSION" =~ - ]]; then
fi
[[ "$ARCHVERSION" =~ .el7a. ]] && ALT="-alt"
-[[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
+[[ -z "$OOT_MODULE" ]] && [[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
# Don't check external file.
# shellcheck disable=SC1090
@@ -870,7 +883,9 @@ fi
[[ -z "$CONFIGFILE" ]] && CONFIGFILE="$SRCDIR"/.config
[[ ! -e "$CONFIGFILE" ]] && die "can't find config file"
if [[ ! "$CONFIGFILE" -ef "$SRCDIR"/.config ]] ; then
- cp -f "$CONFIGFILE" "$SRCDIR/.config" || die
+ if [[ -z "$OOT_MODULE" ]] ; then
+ cp -f "$CONFIGFILE" "$SRCDIR/.config" || die
+ fi
fi
# kernel option checking
@@ -947,7 +962,7 @@ if [[ "$CONFIG_CC_IS_CLANG" -eq 1 ]]; then
fi
if [[ "$SKIPCOMPILERCHECK" -eq 0 ]]; then
- if [[ -n "$OOT_MODULE" ]]; then
+ if [[ -n "$OOT_MODULE" ]] && [[ "$OOT_MODULE" != "yes" ]]; then
target="$OOT_MODULE"
else
target="$VMLINUX"
@@ -1005,10 +1020,16 @@ fi
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-make "${MAKEVARS[@]}" "-j$CPUS" $TARGETS 2>&1 | logger || die
+if [[ -z "$USERMODBUILDDIR" ]]; then
+ make "${MAKEVARS[@]}" "-j$CPUS" $TARGETS 2>&1 | logger || die
+else
+ make "${MAKEVARS[@]}" -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" $USERMODFLAGS "-j$CPUS" $TARGETS 2>&1 | logger || die
+fi
# Save original module symvers
-cp -f "$SRCDIR/Module.symvers" "$TEMPDIR/Module.symvers" || die
+if [[ "$OOT_MODULE" != "yes" ]]; then
+ cp -f "$SRCDIR/Module.symvers" "$TEMPDIR/Module.symvers" || die
+fi
echo "Building patched source"
apply_patches
@@ -1018,7 +1039,12 @@ export KPATCH_GCC_SRCDIR="$SRCDIR"
save_env
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-KBUILD_MODPOST_WARN=1 make "${MAKEVARS[@]}" "-j$CPUS" $TARGETS 2>&1 | logger || die
+
+if [[ -z "$USERMODBUILDDIR" ]]; then
+ KBUILD_MODPOST_WARN=1 make "${MAKEVARS[@]}" "-j$CPUS" $TARGETS 2>&1 | logger || die
+else
+ KBUILD_MODPOST_WARN=1 make "${MAKEVARS[@]}" -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" $USERMODFLAGS "-j$CPUS" $TARGETS 2>&1 | logger || die
+fi
# source.c:(.section+0xFF): undefined reference to `symbol'
grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \
@@ -1033,7 +1059,7 @@ fi
[[ -n "$OOT_MODULE" ]] || grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file"
-if [[ "$CONFIG_MODVERSIONS" -eq 1 ]]; then
+if [[ "$CONFIG_MODVERSIONS" -eq 1 ]] && [[ "$OOT_MODULE" != "yes" ]]; then
while read -ra sym_line; do
if [[ ${#sym_line[@]} -lt 4 ]]; then
die "Malformed ${TEMPDIR}/Module.symvers file"
@@ -1061,7 +1087,11 @@ fi
for i in $(cat "$TEMPDIR/changed_objs")
do
mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die
- cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
+ if [ -z "$USERMODBUILDDIR" ];then
+ cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
+ else
+ cp -f "$i" "$TEMPDIR/patched/$i" || die
+ fi
done
echo "Extracting new and modified ELF sections"
@@ -1095,7 +1125,7 @@ CHANGED=0
ERROR=0
# Prepare OOT module symvers file
-if [[ -n "$OOT_MODULE" ]]; then
+if [[ -n "$OOT_MODULE" ]] && [[ "$OOT_MODULE" != "yes" ]]; then
BUILDDIR="/lib/modules/$ARCHVERSION/build/"
cp -f "$SRCDIR/Module.symvers" "$TEMPDIR/Module.symvers" || die
awk '{ print $1 "\t" $2 "\t" $3 "\t" $4}' "${BUILDDIR}/Module.symvers" >> "$TEMPDIR/Module.symvers"
@@ -1131,6 +1161,14 @@ for i in $FILES; do
KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE"
SYMTAB="${KOBJFILE_PATH}.symtab"
SYMVERS_FILE="$SRCDIR/Module.symvers"
+
+ if [ "$OOT_MODULE" == "yes" ];then
+ BUILDDIR="/lib/modules/$ARCHVERSION/build/"
+ SYMVERS_FILE="$TEMPDIR/Module.symvers"
+ [[ -e $SRCDIR/Module.symvers ]] && cp "$SRCDIR/Module.symvers" "$SYMVERS_FILE"
+ [[ -e $USERMODBUILDDIR/Module.symvers ]] && cp "$USERMODBUILDDIR/Module.symvers" $SYMVERS_FILE
+ awk '{ print $1 "\t" $2 "\t" $3 "\t" $4}' "${BUILDDIR}/Module.symvers" >> "$SYMVERS_FILE"
+ fi
fi
readelf -s --wide "$KOBJFILE_PATH" > "$SYMTAB"
@@ -1283,7 +1321,7 @@ fi
# column containing lines unique to first file.
UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \
<(sort -u "${TEMPDIR}"/new_symbols) | tr '\n' ' ')
-[[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
+[[ -z "$USERMODBUILDDIR" ]] && [[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die
diff --git a/kpatch-build/kpatch-cc b/kpatch-build/kpatch-cc
index 476436f..7ee1655 100755
--- a/kpatch-build/kpatch-cc
+++ b/kpatch-build/kpatch-cc
@@ -24,7 +24,9 @@ if [[ "$TOOLCHAINCMD" =~ ^(.*-)?gcc$ || "$TOOLCHAINCMD" =~ ^(.*-)?clang$ ]] ; th
[[ "$obj" = */.tmp_*.o ]] && obj="${obj/.tmp_/}"
relobj=${obj//$KPATCH_GCC_SRCDIR\//}
- case "$relobj" in
+ tmpobj=$(readlink -f $obj)
+ relobj2=${tmpobj//$KPATCH_GCC_SRCDIR\//}
+ case "$relobj2" in
*.mod.o|\
*built-in.o|\
*built-in.a|\
--
2.23.0

View File

@ -1,133 +0,0 @@
From a1303033db88fa0036387f3a86f71d162bd5c037 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 06:44:06 -0500
Subject: [PATCH 10/23] kpatch-build: enhance for out of tree module
support set USERMODBUILDDIR to build patch for out
of tree module.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 50 ++++++++++++++++++++++++++++++++-------
1 file changed, 42 insertions(+), 8 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 894f0ab..4e38412 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -419,7 +419,11 @@ filter_parent_obj()
local dir="${1}"
local file="${2}"
- grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd"
+ grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd" | while read input; do
+ if [ "$(readlink -f $input)" != "$(readlink -f ${dir}/.${file}.cmd)" ];then
+ echo $input;
+ fi
+ done
}
find_parent_obj() {
@@ -441,6 +445,11 @@ find_parent_obj() {
num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | wc -l)"
[[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
fi
+ if [[ "$num" -eq 0 ]]; then
+ parent="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | head -n1)"
+ num="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
+ [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
+ fi
else
parent="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | head -n1)"
num="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | wc -l)"
@@ -646,6 +655,10 @@ if [[ -n "$SRCRPM" ]]; then
ARCHVERSION="${ARCHVERSION#alt-}"
fi
+if [[ -n "$USERMODBUILDDIR" ]]; then
+ OOT_MODULE="yes"
+fi
+
if [[ -n "$OOT_MODULE" ]] && [[ -z "$USERSRCDIR" ]]; then
warn "--oot-module requires --sourcedir"
exit 1
@@ -663,7 +676,7 @@ if [[ -n "$USERSRCDIR" ]]; then
fi
SRCDIR="$USERSRCDIR"
- if [[ -z "$OOT_MODULE" ]]; then
+ if [[ -z "$OOT_MODULE" || "$OOT_MODULE" == "yes" ]]; then
[[ -z "$VMLINUX" ]] && VMLINUX="$SRCDIR"/vmlinux
[[ ! -e "$VMLINUX" ]] && die "can't find vmlinux"
@@ -685,7 +698,7 @@ if [[ "$ARCHVERSION" =~ - ]]; then
fi
[[ "$ARCHVERSION" =~ .el7a. ]] && ALT="-alt"
-[[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
+[[ -z "$OOT_MODULE" ]] && [[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
# Don't check external file.
# shellcheck disable=SC1090
@@ -889,7 +902,11 @@ echo "Building original source"
unset KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make "-j$CPUS" $TARGETS 2>&1 | logger || die
+if [[ -z "$USERMODBUILDDIR" ]]; then
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make "-j$CPUS" $TARGETS 2>&1 | logger || die
+else
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+fi
echo "Building patched source"
apply_patches
@@ -900,9 +917,15 @@ KPATCH_GCC_SRCDIR="$SRCDIR"
export KPATCH_GCC_SRCDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
- KBUILD_MODPOST_WARN=1 \
- make "-j$CPUS" $TARGETS 2>&1 | logger || die
+if [[ -z "$USERMODBUILDDIR" ]]; then
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
+ KBUILD_MODPOST_WARN=1 \
+ make "-j$CPUS" $TARGETS 2>&1 | logger || die
+else
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
+ KBUILD_MODPOST_WARN=1 \
+ make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+fi
# source.c:(.section+0xFF): undefined reference to `symbol'
grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \
@@ -922,7 +945,11 @@ fi
for i in $(cat "$TEMPDIR/changed_objs")
do
mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die
- cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
+ if [ -z "$USERMODBUILDDIR" ];then
+ cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
+ else
+ cp -f "$i" "$TEMPDIR/patched/$i" || die
+ fi
done
echo "Extracting new and modified ELF sections"
@@ -987,6 +1014,13 @@ for i in $FILES; do
KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE"
SYMTAB="${KOBJFILE_PATH}.symtab"
SYMVERS_FILE="$SRCDIR/Module.symvers"
+
+ if [ "$OOT_MODULE" == "yes" ];then
+ BUILDDIR="/lib/modules/$ARCHVERSION/build/"
+ SYMVERS_FILE="$TEMPDIR/Module.symvers"
+ [[ -e $SRCDIR/Module.symvers ]] && cp "$SRCDIR/Module.symvers" "$SYMVERS_FILE"
+ awk '{ print $1 "\t" $2 "\t" $3 "\t" $4}' "${BUILDDIR}/Module.symvers" >> "$SYMVERS_FILE"
+ fi
fi
readelf -s --wide "$KOBJFILE_PATH" > "$SYMTAB"
--
2.18.1

View File

@ -1,7 +1,7 @@
From d170861502e78c396f0283f66f444a496efd11de Mon Sep 17 00:00:00 2001 From 86bae0f77f1e11f6b64eb950c739f7c6b444eb43 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 07:36:59 -0500 Date: Wed, 26 Feb 2020 07:36:59 -0500
Subject: [PATCH 11/23] support c plus kernel module Subject: [PATCH 10/24] support c++ kernel module
support GNU_UNIQUE type symbols. support GNU_UNIQUE type symbols.
support .group section corelation. support .group section corelation.
@ -9,18 +9,17 @@ ignore compile warning for third party modules.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com> Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
--- ---
kpatch-build/create-diff-object.c | 60 +++++++++++++++++++++---------- kpatch-build/create-diff-object.c | 48 ++++++++++++++++++++-----------
kpatch-build/kpatch-build | 2 +- kpatch-build/kpatch-cc | 4 ++-
kpatch-build/kpatch-elf.c | 8 ++++- kpatch-build/kpatch-elf.c | 8 +++++-
kpatch-build/kpatch-gcc | 3 +- kpatch-build/lookup.c | 5 +++-
kpatch-build/lookup.c | 5 ++- 4 files changed, 45 insertions(+), 20 deletions(-)
5 files changed, 55 insertions(+), 23 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index f37d404..d139f45 100644 index 18aff6d..5903803 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -460,7 +460,7 @@ static void kpatch_compare_correlated_nonrela_section(struct section *sec) @@ -539,7 +539,7 @@ static void kpatch_compare_correlated_nonrela_section(struct section *sec)
{ {
struct section *sec1 = sec, *sec2 = sec->twin; struct section *sec1 = sec, *sec2 = sec->twin;
@ -29,7 +28,7 @@ index f37d404..d139f45 100644
memcmp(sec1->data->d_buf, sec2->data->d_buf, sec1->data->d_size)) memcmp(sec1->data->d_buf, sec2->data->d_buf, sec1->data->d_size))
sec->status = CHANGED; sec->status = CHANGED;
else else
@@ -476,7 +476,7 @@ static void kpatch_compare_correlated_section(struct section *sec) @@ -555,7 +555,7 @@ static void kpatch_compare_correlated_section(struct section *sec)
sec1->sh.sh_flags != sec2->sh.sh_flags || sec1->sh.sh_flags != sec2->sh.sh_flags ||
sec1->sh.sh_entsize != sec2->sh.sh_entsize || sec1->sh.sh_entsize != sec2->sh.sh_entsize ||
(sec1->sh.sh_addralign != sec2->sh.sh_addralign && (sec1->sh.sh_addralign != sec2->sh.sh_addralign &&
@ -38,12 +37,12 @@ index f37d404..d139f45 100644
DIFF_FATAL("%s section header details differ from %s", sec1->name, sec2->name); DIFF_FATAL("%s section header details differ from %s", sec1->name, sec2->name);
/* Short circuit for mcount sections, we rebuild regardless */ /* Short circuit for mcount sections, we rebuild regardless */
@@ -913,6 +913,34 @@ static void kpatch_correlate_section(struct section *sec1, struct section *sec2) @@ -1024,6 +1024,34 @@ static void kpatch_correlate_section(struct section *sec_orig,
kpatch_correlate_symbol(sec1->sym, sec2->sym); kpatch_correlate_symbol(sec_orig->sym, sec_patched->sym);
} }
+static int kpatch_correlate_group_section(struct list_head *seclist1, +static int kpatch_correlate_group_section(struct list_head *seclist_orig,
+ struct list_head *seclist2, struct section *sec1, struct section *sec2) + struct list_head *seclist_patched, struct section *sec1, struct section *sec2)
+{ +{
+ unsigned int *data1, *end1, *data2; + unsigned int *data1, *end1, *data2;
+ struct section *isec1, *isec2; + struct section *isec1, *isec2;
@ -56,10 +55,10 @@ index f37d404..d139f45 100644
+ data1++; + data1++;
+ data2++; + data2++;
+ while (data1 < end1) { + while (data1 < end1) {
+ isec1 = find_section_by_index(seclist1, *data1); + isec1 = find_section_by_index(seclist_orig, *data1);
+ if (!isec1) + if (!isec1)
+ ERROR("group section not found"); + ERROR("group section not found");
+ isec2 = find_section_by_index(seclist2, *data2); + isec2 = find_section_by_index(seclist_patched, *data2);
+ if (!isec2) + if (!isec2)
+ ERROR("group section not found"); + ERROR("group section not found");
+ if (strcmp(isec1->name, isec2->name)) + if (strcmp(isec1->name, isec2->name))
@ -70,36 +69,22 @@ index f37d404..d139f45 100644
+ return 0; + return 0;
+} +}
+ +
static void kpatch_correlate_sections(struct list_head *seclist1, struct list_head *seclist2) static void kpatch_correlate_sections(struct list_head *seclist_orig,
struct list_head *seclist_patched)
{ {
struct section *sec1, *sec2; @@ -1047,10 +1075,7 @@ static void kpatch_correlate_sections(struct list_head *seclist_orig,
@@ -931,14 +959,19 @@ static void kpatch_correlate_sections(struct list_head *seclist1, struct list_he * Changed group sections are currently not supported.
continue;
/*
- * Group sections must match exactly to be correlated.
- * Changed group sections are currently not supported.
+ * Group section的格式为
+ * flag
+ * section index
+ * section index
+ * ...
+ *
+ * 当C++代码发生修改时section index可能会发生变化
+ * 这时候我们就比对一下section index所对应的section的
+ * name如果相同我们就认为这两个group是SAME
*/ */
+ if (sec_orig->sh.sh_type == SHT_GROUP) {
if (sec1->sh.sh_type == SHT_GROUP) { - if (sec_orig->data->d_size != sec_patched->data->d_size)
- if (sec1->data->d_size != sec2->data->d_size)
- continue; - continue;
- if (memcmp(sec1->data->d_buf, sec2->data->d_buf, - if (memcmp(sec_orig->data->d_buf, sec_patched->data->d_buf,
- sec1->data->d_size)) - sec_orig->data->d_size))
+ if (kpatch_correlate_group_section(seclist1, seclist2, sec1, sec2)) + if (kpatch_correlate_group_section(seclist_orig, seclist_patched, sec_orig, sec_patched))
continue; continue;
} }
@@ -1521,17 +1554,6 @@ static void kpatch_verify_patchability(struct kpatch_elf *kelf) @@ -1725,17 +1750,6 @@ static void kpatch_verify_patchability(struct kpatch_elf *kelf)
errs++; errs++;
} }
@ -117,24 +102,26 @@ index f37d404..d139f45 100644
/* /*
* ensure we aren't including .data.* or .bss.* * ensure we aren't including .data.* or .bss.*
* (.data.unlikely and .data.once is ok b/c it only has __warned vars) * (.data.unlikely and .data.once is ok b/c it only has __warned vars)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build diff --git a/kpatch-build/kpatch-cc b/kpatch-build/kpatch-cc
index 4e38412..4896136 100755 index 7ee1655..80d310c 100755
--- a/kpatch-build/kpatch-build --- a/kpatch-build/kpatch-cc
+++ b/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-cc
@@ -1157,7 +1157,7 @@ fi @@ -13,7 +13,9 @@ fi
# column containing lines unique to first file.
UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \
<(sort -u "${TEMPDIR}"/new_symbols) | tr '\n' ' ')
-[[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
+[[ -z "$USERMODBUILDDIR" ]] && [[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die declare -a args=("$@")
-if [[ "$TOOLCHAINCMD" =~ ^(.*-)?gcc$ || "$TOOLCHAINCMD" =~ ^(.*-)?clang$ ]] ; then
+if [[ "$TOOLCHAINCMD" =~ ^(.*-)?gcc$ ||
+ "$TOOLCHAINCMD" =~ ^(.*-)?g\+\+$ ||
+ "$TOOLCHAINCMD" =~ ^(.*-)?clang$ ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c
index c6af59e..f76a9eb 100644 index 68d5c86..2df9105 100644
--- a/kpatch-build/kpatch-elf.c --- a/kpatch-build/kpatch-elf.c
+++ b/kpatch-build/kpatch-elf.c +++ b/kpatch-build/kpatch-elf.c
@@ -710,8 +710,14 @@ void kpatch_reindex_elements(struct kpatch_elf *kelf) @@ -712,8 +712,14 @@ void kpatch_reindex_elements(struct kpatch_elf *kelf)
unsigned int index; unsigned int index;
index = 1; /* elf write function handles NULL section 0 */ index = 1; /* elf write function handles NULL section 0 */
@ -150,25 +137,11 @@ index c6af59e..f76a9eb 100644
index = 0; index = 0;
list_for_each_entry(sym, &kelf->symbols, list) { list_for_each_entry(sym, &kelf->symbols, list) {
diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc
index 35d7c1c..6ad6ebc 100755
--- a/kpatch-build/kpatch-gcc
+++ b/kpatch-build/kpatch-gcc
@@ -13,7 +13,8 @@ fi
declare -a args=("$@")
-if [[ "$TOOLCHAINCMD" =~ "${ARCH_COMPILE}gcc" ]] ; then
+if [[ "$TOOLCHAINCMD" =~ "${ARCH_COMPILE}gcc" ||
+ "$TOOLCHAINCMD" =~ "${ARCH_COMPILE}g++" ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index 8387e8b..4e2fcb9 100644 index 0323c61..e81e934 100644
--- a/kpatch-build/lookup.c --- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c +++ b/kpatch-build/lookup.c
@@ -255,6 +255,8 @@ static void symtab_read(struct lookup_table *table, char *path) @@ -304,6 +304,8 @@ static void symtab_read(struct lookup_table *table, char *path)
table->obj_syms[i].bind = STB_GLOBAL; table->obj_syms[i].bind = STB_GLOBAL;
} else if (!strcmp(bind, "WEAK")) { } else if (!strcmp(bind, "WEAK")) {
table->obj_syms[i].bind = STB_WEAK; table->obj_syms[i].bind = STB_WEAK;
@ -177,16 +150,16 @@ index 8387e8b..4e2fcb9 100644
} else { } else {
ERROR("unknown symbol bind %s", bind); ERROR("unknown symbol bind %s", bind);
} }
@@ -431,7 +433,8 @@ int lookup_global_symbol(struct lookup_table *table, char *name, @@ -528,7 +530,8 @@ static bool lookup_global_symbol(struct lookup_table *table, char *name,
memset(result, 0, sizeof(*result)); memset(result, 0, sizeof(*result));
for_each_obj_symbol(i, sym, table) { for_each_obj_symbol(i, sym, table) {
- if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) && - if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) &&
+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK ++ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK
+ || sym->bind == STB_GNU_UNIQUE) && ++ || sym->bind == STB_GNU_UNIQUE) &&
!strcmp(sym->name, name)) { !strcmp(sym->name, name)) {
result->value = sym->value;
result->size = sym->size; if (result->objname)
-- --
2.18.1 2.23.0

View File

@ -1,7 +1,7 @@
From 8dbdf64abc81a8c6f9ec71a4187eb7db9b81d090 Mon Sep 17 00:00:00 2001 From 34a0c47eb0f786222b3f2e1fe544f71687920943 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 22:03:55 -0500 Date: Wed, 26 Feb 2020 22:03:55 -0500
Subject: [PATCH 12/23] symbol lookup enhancement Subject: [PATCH 11/24] symbol lookup enhancement
For symbols which have same name in one module or have For symbols which have same name in one module or have
length longger than KSYM_NAME_LEN(128 bytes). we add length longger than KSYM_NAME_LEN(128 bytes). we add
@ -13,13 +13,13 @@ style.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com> Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
--- ---
kmod/patch/kpatch-patch.h | 4 + kmod/patch/kpatch-patch.h | 4 +
kpatch-build/create-diff-object.c | 53 +++++++++++- kpatch-build/create-diff-object.c | 40 +++++++-
kpatch-build/create-klp-module.c | 25 +++++- kpatch-build/create-klp-module.c | 25 ++++-
kpatch-build/kpatch-build | 12 +++ kpatch-build/kpatch-build | 12 +++
kpatch-build/kpatch-intermediate.h | 2 + kpatch-build/kpatch-intermediate.h | 2 +
kpatch-build/lookup.c | 129 ++++++++++++++++++++++++++++- kpatch-build/lookup.c | 159 ++++++++++++++++++++++++++++-
kpatch-build/lookup.h | 13 +++ kpatch-build/lookup.h | 15 +++
7 files changed, 230 insertions(+), 8 deletions(-) 7 files changed, 247 insertions(+), 10 deletions(-)
diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h
index da4f6a0..9df7818 100644 index da4f6a0..9df7818 100644
@ -44,74 +44,61 @@ index da4f6a0..9df7818 100644
struct kpatch_pre_patch_callback { struct kpatch_pre_patch_callback {
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index d139f45..73c557b 100644 index 5903803..ea1e01b 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -2753,6 +2753,29 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf, @@ -3032,6 +3032,14 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
funcs[index].old_size = result.size; funcs[index].old_size = symbol.size;
funcs[index].new_size = sym->sym.st_size; funcs[index].new_size = sym->sym.st_size;
funcs[index].sympos = result.pos; funcs[index].sympos = symbol.sympos;
+ if (lookup_is_duplicate_symbol(table, sym->name, objname, result.pos)) { + if (lookup_is_duplicate_symbol(table, sym->name, objname, symbol.sympos)) {
+ struct lookup_refsym refsym; + if (!strcmp(objname, "vmlinux")) {
+ long offset; + symbol.sympos = get_vmlinux_duplicate_symbol_pos(table, sym->name, symbol.addr);
+ + log_debug("update %s sympos from %ld to %ld\n",
+ if (lookup_ref_symbol_offset(table, sym->name, &refsym, + sym->name, funcs[index].sympos, symbol.sympos);
+ objname, &offset)) + funcs[index].sympos = symbol.sympos;
+ ERROR("unresolvable ambiguity on symbol %s\n", sym->name); + }
+
+ funcs[index].ref_offset = offset;
+
+ /*
+ * Add a relocation that will populate
+ * the funcs[index].ref_name field.
+ */
+ ALLOC_LINK(rela, &relasec->relas);
+ rela->sym = strsym;
+ rela->type = absolute_rela_type;
+ rela->addend = offset_of_string(&kelf->strings, refsym.name);
+ rela->offset = (unsigned int)(index * sizeof(*funcs) +
+ offsetof(struct kpatch_patch_func, ref_name));
+
+ } + }
+
/* /*
* Add a relocation that will populate * Add a relocation that will populate the
@@ -2772,7 +2795,8 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf, @@ -3050,7 +3058,8 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
ALLOC_LINK(rela, &relasec->relas); ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym; rela->sym = strsym;
rela->type = absolute_rela_type; rela->type = ABSOLUTE_RELA_TYPE;
- rela->addend = offset_of_string(&kelf->strings, sym->name); - rela->addend = offset_of_string(&kelf->strings, sym->name);
+ rela->addend = offset_of_string(&kelf->strings, + rela->addend = offset_of_string(&kelf->strings,
+ strndup(sym->name, KSYM_NAME_LEN-1)); + strndup(sym->name, KSYM_NAME_LEN-1));
rela->offset = (unsigned int)(index * sizeof(*funcs) + rela->offset = (unsigned int)(index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func, name)); offsetof(struct kpatch_patch_func, name));
@@ -2891,6 +2915,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, @@ -3274,6 +3283,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
struct lookup_result result; bool special;
char *sym_objname; bool vmlinux = !strcmp(objname, "vmlinux");
int ret, vmlinux, external; struct special_section *s;
+ long ref_offset; + long ref_offset;
vmlinux = !strcmp(objname, "vmlinux"); /* count rela entries that need to be dynamic */
nr = 0;
@@ -3102,12 +3127,32 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, @@ -3370,12 +3380,34 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
log_debug("lookup for %s @ 0x%016lx len %lu\n", rela->sym->name, symbol.objname,
rela->sym->name, result.value, result.size); symbol.sympos);
+ ref_offset = 0; + ref_offset = 0;
/* Fill in ksyms[index] */ /* Fill in ksyms[index] */
if (vmlinux) if (vmlinux)
ksyms[index].src = result.value; ksyms[index].src = symbol.addr;
- else - else
+ else { + else {
/* for modules, src is discovered at runtime */ /* for modules, src is discovered at runtime */
ksyms[index].src = 0; ksyms[index].src = 0;
+ }
+
+ if (lookup_is_duplicate_symbol(table, rela->sym->name, objname, + if (lookup_is_duplicate_symbol(table, rela->sym->name, objname,
+ result.pos)) { + symbol.sympos)) {
+ struct lookup_refsym refsym; + struct lookup_refsym refsym;
+ +
+ if (lookup_ref_symbol_offset(table, rela->sym->name, + if (lookup_ref_symbol_offset(table, rela->sym,
+ &refsym, objname, &ref_offset)) + &refsym, objname, &ref_offset))
+ ERROR("unresolvable ambiguity on symbol %s\n", + ERROR("unresolvable ambiguity on symbol %s\n",
+ rela->sym->name); + rela->sym->name);
@ -119,36 +106,36 @@ index d139f45..73c557b 100644
+ /* add rela to fill in ref_name field */ + /* add rela to fill in ref_name field */
+ ALLOC_LINK(rela2, &krela_sec->rela->relas); + ALLOC_LINK(rela2, &krela_sec->rela->relas);
+ rela2->sym = strsym; + rela2->sym = strsym;
+ rela2->type = absolute_rela_type; + rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->addend = offset_of_string(&kelf->strings, + rela2->addend = offset_of_string(&kelf->strings,
+ refsym.name); + refsym.name);
+ rela2->offset = (unsigned int)(index * sizeof(*krelas) + + rela2->offset = (unsigned int)(index * sizeof(*krelas) +
+ offsetof(struct kpatch_relocation, ref_name)); + offsetof(struct kpatch_relocation, ref_name));
+ } + }
+ } +
ksyms[index].pos = result.pos; ksyms[index].sympos = symbol.sympos;
ksyms[index].type = rela->sym->type; ksyms[index].type = rela->sym->type;
ksyms[index].bind = rela->sym->bind; ksyms[index].bind = rela->sym->bind;
@@ -3116,7 +3161,8 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, @@ -3384,7 +3416,8 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
ALLOC_LINK(rela2, &ksym_sec->rela->relas); ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym; rela2->sym = strsym;
rela2->type = absolute_rela_type; rela2->type = ABSOLUTE_RELA_TYPE;
- rela2->addend = offset_of_string(&kelf->strings, rela->sym->name); - rela2->addend = offset_of_string(&kelf->strings, rela->sym->name);
+ rela2->addend = offset_of_string(&kelf->strings, + rela2->addend = offset_of_string(&kelf->strings,
+ strndup(rela->sym->name, KSYM_NAME_LEN-1)); + strndup(rela->sym->name, KSYM_NAME_LEN-1));
rela2->offset = (unsigned int)(index * sizeof(*ksyms) + \ rela2->offset = (unsigned int)(index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, name)); offsetof(struct kpatch_symbol, name));
@@ -3135,6 +3181,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, @@ -3403,6 +3436,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
krelas[index].addend = rela->addend; krelas[index].addend = rela->addend;
krelas[index].type = rela->type; krelas[index].type = rela->type;
krelas[index].external = external; krelas[index].external = !vmlinux && symbol.exported;
+ krelas[index].ref_offset = ref_offset; + krelas[index].ref_offset = ref_offset;
/* add rela to fill in krelas[index].dest field */ /* add rela to fill in krelas[index].dest field */
ALLOC_LINK(rela2, &krela_sec->rela->relas); ALLOC_LINK(rela2, &krela_sec->rela->relas);
diff --git a/kpatch-build/create-klp-module.c b/kpatch-build/create-klp-module.c diff --git a/kpatch-build/create-klp-module.c b/kpatch-build/create-klp-module.c
index a97b146..5b89b73 100644 index d1b03fe..547e587 100644
--- a/kpatch-build/create-klp-module.c --- a/kpatch-build/create-klp-module.c
+++ b/kpatch-build/create-klp-module.c +++ b/kpatch-build/create-klp-module.c
@@ -38,7 +38,9 @@ enum loglevel loglevel = NORMAL; @@ -38,7 +38,9 @@ enum loglevel loglevel = NORMAL;
@ -166,11 +153,11 @@ index a97b146..5b89b73 100644
objname = strings + rela->addend; objname = strings + rela->addend;
- snprintf(pos, 32, "%lu", ksym->pos); - snprintf(pos, 32, "%lu", ksym->sympos);
/* .klp.sym.objname.name,pos */ /* .klp.sym.objname.name,pos */
- snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos); - snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos);
+ if (!ref_name) { + if (!ref_name) {
+ snprintf(pos, 32, "%lu", ksym->pos); + snprintf(pos, 32, "%lu", ksym->sympos);
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos); + snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos);
+ } else { + } else {
+ snprintf(pos, 32, "%ld", ref_offset); + snprintf(pos, 32, "%ld", ref_offset);
@ -213,10 +200,10 @@ index a97b146..5b89b73 100644
ERROR("error finding or adding ksym to symtab"); ERROR("error finding or adding ksym to symtab");
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 4896136..8bef7fb 100755 index 3aca1f3..722d362 100755
--- a/kpatch-build/kpatch-build --- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build
@@ -1015,6 +1015,18 @@ for i in $FILES; do @@ -1162,6 +1162,18 @@ for i in $FILES; do
SYMTAB="${KOBJFILE_PATH}.symtab" SYMTAB="${KOBJFILE_PATH}.symtab"
SYMVERS_FILE="$SRCDIR/Module.symvers" SYMVERS_FILE="$SRCDIR/Module.symvers"
@ -224,9 +211,9 @@ index 4896136..8bef7fb 100755
+ remove_patches + remove_patches
+ cd "$SRCDIR" || die + cd "$SRCDIR" || die
+ if [ -z "$USERMODBUILDDIR" ];then + if [ -z "$USERMODBUILDDIR" ];then
+ CROSS_COMPILE="$ARCH_COMPILE" make "-j$CPUS" ${KOBJFILE} 2>&1 | logger || die + make "-j$CPUS" $TARGETS 2>&1 | logger || die
+ else + else
+ CROSS_COMPILE="$ARCH_COMPILE" make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die + make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" $USERMODFLAGS "-j$CPUS" $TARGETS 2>&1 | logger || die
+ fi + fi
+ cp ${KOBJFILE} ${KOBJFILE_PATH} + cp ${KOBJFILE} ${KOBJFILE_PATH}
+ apply_patches + apply_patches
@ -236,7 +223,7 @@ index 4896136..8bef7fb 100755
BUILDDIR="/lib/modules/$ARCHVERSION/build/" BUILDDIR="/lib/modules/$ARCHVERSION/build/"
SYMVERS_FILE="$TEMPDIR/Module.symvers" SYMVERS_FILE="$TEMPDIR/Module.symvers"
diff --git a/kpatch-build/kpatch-intermediate.h b/kpatch-build/kpatch-intermediate.h diff --git a/kpatch-build/kpatch-intermediate.h b/kpatch-build/kpatch-intermediate.h
index 7230cd4..5322e7a 100644 index 2036cb3..2589959 100644
--- a/kpatch-build/kpatch-intermediate.h --- a/kpatch-build/kpatch-intermediate.h
+++ b/kpatch-build/kpatch-intermediate.h +++ b/kpatch-build/kpatch-intermediate.h
@@ -39,6 +39,8 @@ struct kpatch_relocation { @@ -39,6 +39,8 @@ struct kpatch_relocation {
@ -249,10 +236,10 @@ index 7230cd4..5322e7a 100644
struct kpatch_arch { struct kpatch_arch {
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index 4e2fcb9..1dd183f 100644 index e81e934..238541c 100644
--- a/kpatch-build/lookup.c --- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c +++ b/kpatch-build/lookup.c
@@ -44,6 +44,7 @@ struct object_symbol { @@ -45,6 +45,7 @@ struct object_symbol {
unsigned long size; unsigned long size;
char *name; char *name;
int type, bind; int type, bind;
@ -260,18 +247,18 @@ index 4e2fcb9..1dd183f 100644
}; };
struct export_symbol { struct export_symbol {
@@ -248,6 +249,7 @@ static void symtab_read(struct lookup_table *table, char *path) @@ -297,6 +298,7 @@ static void symtab_read(struct lookup_table *table, char *path)
table->obj_syms[i].value = value; table->obj_syms[i].addr = addr;
table->obj_syms[i].size = strtoul(size, NULL, 0); table->obj_syms[i].size = strtoul(size, NULL, 0);
+ table->obj_syms[i].sec_index = atoi(ndx); + table->obj_syms[i].sec_index = atoi(ndx);
if (!strcmp(bind, "LOCAL")) { if (!strcmp(bind, "LOCAL")) {
table->obj_syms[i].bind = STB_LOCAL; table->obj_syms[i].bind = STB_LOCAL;
@@ -398,6 +400,17 @@ int lookup_local_symbol(struct lookup_table *table, char *name, @@ -457,6 +459,17 @@ static bool lookup_local_symbol(struct lookup_table *table,
for_each_obj_symbol(i, sym, table) { if (sym->bind == STB_LOCAL && !strcmp(sym->name,
if (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) lookup_sym->name))
pos++; sympos++;
+ else { + else {
+ /* + /*
+ * symbol name longer than KSYM_NAME_LEN will be truncated + * symbol name longer than KSYM_NAME_LEN will be truncated
@ -279,22 +266,23 @@ index 4e2fcb9..1dd183f 100644
+ * name. we need to add pos for symbols which have same + * name. we need to add pos for symbols which have same
+ * KSYM_NAME_LEN-1 long prefix. + * KSYM_NAME_LEN-1 long prefix.
+ */ + */
+ if (strlen(name) >= KSYM_NAME_LEN-1 && + if (strlen(lookup_sym->name) >= KSYM_NAME_LEN-1 &&
+ !strncmp(sym->name, name, KSYM_NAME_LEN-1)) + !strncmp(sym->name, lookup_sym->name, KSYM_NAME_LEN-1))
+ pos++; + sympos++;
+ } + }
if (table->local_syms == sym) { if (lookup_sym->lookup_table_file_sym == sym) {
in_file = 1; in_file = 1;
@@ -429,16 +442,27 @@ int lookup_global_symbol(struct lookup_table *table, char *name, @@ -527,11 +540,22 @@ static bool lookup_global_symbol(struct lookup_table *table, char *name,
struct lookup_result *result)
{ {
struct object_symbol *sym; struct object_symbol *sym;
+ unsigned long pos = 0;
int i; int i;
+ unsigned long sympos = 0;
memset(result, 0, sizeof(*result)); memset(result, 0, sizeof(*result));
for_each_obj_symbol(i, sym, table) { for_each_obj_symbol(i, sym, table) {
-+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK
-+ || sym->bind == STB_GNU_UNIQUE) &&
+ /* + /*
+ * symbol name longer than KSYM_NAME_LEN will be truncated + * symbol name longer than KSYM_NAME_LEN will be truncated
+ * by kernel, so we can not find it using its original + * by kernel, so we can not find it using its original
@ -303,22 +291,27 @@ index 4e2fcb9..1dd183f 100644
+ */ + */
+ if (strlen(name) >= KSYM_NAME_LEN-1 && + if (strlen(name) >= KSYM_NAME_LEN-1 &&
+ !strncmp(sym->name, name, KSYM_NAME_LEN-1)) + !strncmp(sym->name, name, KSYM_NAME_LEN-1))
+ pos++; + sympos++;
+ +
if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK + if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK
|| sym->bind == STB_GNU_UNIQUE) && + || sym->bind == STB_GNU_UNIQUE) &&
!strcmp(sym->name, name)) { !strcmp(sym->name, name)) {
result->value = sym->value;
result->size = sym->size;
- result->pos = 0; /* always 0 for global symbols */
+ result->pos = pos;
return 0;
}
}
@@ -485,6 +509,109 @@ char *lookup_exported_symbol_objname(struct lookup_table *table, char *name)
return NULL;
}
if (result->objname)
@@ -540,7 +564,7 @@ static bool lookup_global_symbol(struct lookup_table *table, char *name,
result->objname = table->objname;
result->addr = sym->addr;
result->size = sym->size;
- result->sympos = 0; /* always 0 for global symbols */
+ result->sympos = sympos;
result->global = true;
result->exported = is_exported(table, name);
}
@@ -560,3 +584,132 @@ bool lookup_symbol(struct lookup_table *table, struct symbol *sym,
return lookup_exported_symbol(table, sym->name, result);
}
+
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name, +int lookup_is_duplicate_symbol(struct lookup_table *table, char *name,
+ char *objname, unsigned long pos) + char *objname, unsigned long pos)
+{ +{
@ -349,20 +342,21 @@ index 4e2fcb9..1dd183f 100644
+ return 0; + return 0;
+} +}
+ +
+struct object_symbol *lookup_find_symbol_by_name(struct lookup_table *table, char *name) +struct object_symbol *lookup_find_symbol(struct lookup_table *table,
+ struct symbol *lookup_sym)
+{ +{
+ struct object_symbol *sym; + struct object_symbol *sym;
+ unsigned long pos = 0; + unsigned long pos = 0;
+ int i, match = 0, in_file = 0; + int i, match = 0, in_file = 0;
+ +
+ if (!table->local_syms) + if (!lookup_sym->lookup_table_file_sym)
+ return NULL; + return NULL;
+ +
+ for_each_obj_symbol(i, sym, table) { + for_each_obj_symbol(i, sym, table) {
+ if (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) + if (sym->bind == STB_LOCAL && !strcmp(sym->name, lookup_sym->name))
+ pos++; + pos++;
+ +
+ if (table->local_syms == sym) { + if (lookup_sym->lookup_table_file_sym == sym) {
+ in_file = 1; + in_file = 1;
+ continue; + continue;
+ } + }
@ -373,7 +367,7 @@ index 4e2fcb9..1dd183f 100644
+ if (sym->type == STT_FILE) + if (sym->type == STT_FILE)
+ break; + break;
+ +
+ if (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) { + if (sym->bind == STB_LOCAL && !strcmp(sym->name, lookup_sym->name)) {
+ match = 1; + match = 1;
+ break; + break;
+ } + }
@ -382,7 +376,7 @@ index 4e2fcb9..1dd183f 100644
+ if (!match) { + if (!match) {
+ for_each_obj_symbol(i, sym, table) { + for_each_obj_symbol(i, sym, table) {
+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) && + if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) &&
+ !strcmp(sym->name, name)) { + !strcmp(sym->name, lookup_sym->name)) {
+ return sym; + return sym;
+ } + }
+ } + }
@ -392,29 +386,30 @@ index 4e2fcb9..1dd183f 100644
+ return sym; + return sym;
+} +}
+ +
+int lookup_ref_symbol_offset(struct lookup_table *table, char *name, +int lookup_ref_symbol_offset(struct lookup_table *table,
+ struct symbol *lookup_sym,
+ struct lookup_refsym *refsym, + struct lookup_refsym *refsym,
+ char *objname, long *offset) + char *objname, long *offset)
+{ +{
+ struct object_symbol *orig_sym, *sym; + struct object_symbol *orig_sym, *sym;
+ int i; + int i;
+ +
+ orig_sym = lookup_find_symbol_by_name(table, name); + orig_sym = lookup_find_symbol(table, lookup_sym);
+ if (!orig_sym) + if (!orig_sym)
+ ERROR("lookup_ref_symbol_offset"); + ERROR("lookup_ref_symbol_offset");
+ memset(refsym, 0, sizeof(*refsym)); + memset(refsym, 0, sizeof(*refsym));
+ +
+ /*find a unique symbol in the same section first*/ + /*find a unique symbol in the same section first*/
+ for_each_obj_symbol(i, sym, table) { + for_each_obj_symbol(i, sym, table) {
+ if (!strcmp(sym->name, name) || sym->type == STT_FILE || + if (!strcmp(sym->name, lookup_sym->name) || sym->type == STT_FILE ||
+ sym->sec_index != orig_sym->sec_index || + sym->sec_index != orig_sym->sec_index ||
+ strchr(sym->name, '.')) + strchr(sym->name, '.'))
+ continue; + continue;
+ +
+ if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) { + if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
+ refsym->name = sym->name; + refsym->name = sym->name;
+ refsym->value = sym->value; + refsym->addr = sym->addr;
+ *offset = (long)orig_sym->value - (long)sym->value; + *offset = (long)orig_sym->addr- (long)sym->addr;
+ return 0; + return 0;
+ } + }
+ } + }
@ -422,46 +417,66 @@ index 4e2fcb9..1dd183f 100644
+ return 1; + return 1;
+} +}
+ +
#if 0 /* for local testing */ +/*
static void find_this(struct lookup_table *table, char *sym, char *hint) + * In case sometimes the sympos of duplicate symbols are different in vmlinux and
{ + * /proc/kallsyms, and causes lookup_local_symbol to save wrong sympos in result,
+ * this function returns correct sympos of the symbol, by comparing
+ * address value with the symbol in vmlinux symbol table.
+ */
+unsigned long get_vmlinux_duplicate_symbol_pos(struct lookup_table *table,
+ char *name, unsigned long addr)
+{
+ struct object_symbol *sym;
+ unsigned long pos = 1;
+ int i;
+
+ for_each_obj_symbol(i, sym, table) {
+ if (strcmp(sym->name, name))
+ continue;
+
+ if (sym->addr < addr)
+ pos++;
+ }
+
+ return pos;
+}
diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h
index 420d0f0..6f640fd 100644 index e1277f1..21aceb4 100644
--- a/kpatch-build/lookup.h --- a/kpatch-build/lookup.h
+++ b/kpatch-build/lookup.h +++ b/kpatch-build/lookup.h
@@ -1,6 +1,9 @@ @@ -4,6 +4,8 @@
#ifndef _LOOKUP_H_ #include <stdbool.h>
#define _LOOKUP_H_ #include "kpatch-elf.h"
+#include "kpatch-elf.h"
+#define KSYM_NAME_LEN 128 +#define KSYM_NAME_LEN 128
+ +
struct lookup_table; struct lookup_table;
struct lookup_result { struct lookup_result {
@@ -14,6 +17,11 @@ struct sym_compare_type { @@ -14,10 +16,23 @@ struct lookup_result {
int type; bool global, exported;
}; };
+struct lookup_refsym { +struct lookup_refsym {
+ char *name; + char *name;
+ unsigned long value; + unsigned long addr;
+}; +};
+ +
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path, struct lookup_table *lookup_open(char *symtab_path, char *objname,
char *hint, struct sym_compare_type *locals); char *symvers_path, struct kpatch_elf *kelf);
void lookup_close(struct lookup_table *table); void lookup_close(struct lookup_table *table);
@@ -23,5 +31,10 @@ int lookup_global_symbol(struct lookup_table *table, char *name, bool lookup_symbol(struct lookup_table *table, struct symbol *sym,
struct lookup_result *result); struct lookup_result *result);
int lookup_is_exported_symbol(struct lookup_table *table, char *name);
char *lookup_exported_symbol_objname(struct lookup_table *table, char *name);
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name, +int lookup_is_duplicate_symbol(struct lookup_table *table, char *name,
+ char *objname, unsigned long pos); + char *objname, unsigned long pos);
+int lookup_ref_symbol_offset(struct lookup_table *table, char *name, +int lookup_ref_symbol_offset(struct lookup_table *table,
+ struct symbol *lookup_sym,
+ struct lookup_refsym *refsym, char *objname, + struct lookup_refsym *refsym, char *objname,
+ long *offset); + long *offset);
+unsigned long get_vmlinux_duplicate_symbol_pos(struct lookup_table *table, char *name,
+ unsigned long addr);
#endif /* _LOOKUP_H_ */ #endif /* _LOOKUP_H_ */
-- --
2.18.1 2.23.0

View File

@ -0,0 +1,126 @@
From 344dfff72d5a2d574d8d7804277bf587af45743d Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 20:28:13 -0500
Subject: [PATCH 12/24] Add running kernel symbol table to help symbol lookup
For some duplicate symbols whose section have no other
symbols, we need running kernel symbol table to help
symbol lookup.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/lookup.c | 73 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index 238541c..2cdff67 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -46,6 +46,7 @@ struct object_symbol {
char *name;
int type, bind;
int sec_index;
+ unsigned long kaddr;
};
struct export_symbol {
@@ -409,10 +410,62 @@ static void symvers_read(struct lookup_table *table, char *path)
fclose(file);
}
+static void ksymtab_read(struct lookup_table *table, char *path)
+{
+ FILE *file;
+ struct object_symbol *sym, *sym1, *sym2;
+ unsigned long value;
+ int i, j, idx;
+ char line[256], name[256], type[256], mod[256];
+
+ idx = 0;
+ file = fopen(path, "r");
+ if (file == NULL)
+ ERROR("fopen");
+
+ while (fgets(line, 256, file)) {
+ if (sscanf(line, "%lx %s %s [%s]\n",
+ &value, type, name, mod) != 4)
+ continue;
+
+ if (name[0] == '$')
+ continue;
+
+ i = idx;
+ for_each_obj_symbol_continue(i, sym, table) {
+ if (!strncmp(sym->name, name, KSYM_NAME_LEN-1)) {
+ sym->kaddr = value;
+ idx = i + 1;
+ break;
+ }
+ }
+ }
+
+ for_each_obj_symbol(i, sym1, table) {
+ if (sym1->kaddr == 0)
+ continue;
+ for_each_obj_symbol(j, sym2, table) {
+ if (sym2->kaddr == 0)
+ continue;
+ if (sym1 == sym2)
+ continue;
+ if (sym1->sec_index != sym2->sec_index)
+ continue;
+ if ((long)sym1->addr - (long)sym2->addr ==
+ (long)sym1->kaddr - (long)sym2->kaddr)
+ continue;
+
+ ERROR("base mismatch(symbol offset)");
+ }
+ }
+ fclose(file);
+}
+
struct lookup_table *lookup_open(char *symtab_path, char *objname,
char *symvers_path, struct kpatch_elf *kelf)
{
struct lookup_table *table;
+ char *kallsyms;
table = malloc(sizeof(*table));
if (!table)
@@ -422,6 +475,9 @@ struct lookup_table *lookup_open(char *symtab_path, char *objname,
table->objname = objname;
symtab_read(table, symtab_path);
symvers_read(table, symvers_path);
+ kallsyms = getenv("KALLSYMS");
+ if (kallsyms)
+ ksymtab_read(table, kallsyms);
find_local_syms_multiple(table, kelf);
@@ -687,6 +743,23 @@ int lookup_ref_symbol_offset(struct lookup_table *table,
}
}
+ if (orig_sym->kaddr == 0)
+ return 1;
+
+ /*find a unique symbol has kaddr*/
+ for_each_obj_symbol(i, sym, table) {
+ if (!strcmp(sym->name, lookup_sym->name) || sym->type == STT_FILE ||
+ sym->kaddr == 0 || strchr(sym->name, '.'))
+ continue;
+
+ if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
+ refsym->name = sym->name;
+ refsym->addr = 0;
+ *offset = (long)orig_sym->kaddr - (long)sym->kaddr;
+ return 0;
+ }
+ }
+
return 1;
}
--
2.23.0

View File

@ -1,172 +0,0 @@
From 5e6c1b2c91af547ad53faafeec20cddaedf7aaa4 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 20:28:13 -0500
Subject: [PATCH 13/23] Add running kernel symbol table to help symbol lookup
For some duplicate symbols whose section have no other
symbols, we need running kernel symbol table to help
symbol lookup.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 7 ++-
kpatch-build/lookup.c | 74 ++++++++++++++++++++++++++++++-
kpatch-build/lookup.h | 3 +-
3 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 73c557b..c5320d4 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -3597,6 +3597,7 @@ int main(int argc, char *argv[])
struct sym_compare_type *base_locals, *sym_comp;
char *no_profiling_calls = NULL;
char *gcc_add_option = NULL, *mlongcall = NULL;
+ char *kallsyms;
arguments.debug = 0;
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -3710,8 +3711,12 @@ int main(int argc, char *argv[])
*/
kpatch_elf_teardown(kelf_patched);
+ kallsyms = getenv("KALLSYMS");
+ if (kallsyms)
+ log_debug("kallsyms file:%s\n", kallsyms);
+
/* create symbol lookup table */
- lookup = lookup_open(parent_symtab, mod_symvers, hint, base_locals);
+ lookup = lookup_open(parent_symtab, mod_symvers, hint, base_locals, kallsyms);
for (sym_comp = base_locals; sym_comp && sym_comp->name; sym_comp++) {
free(sym_comp->name);
}
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index 1dd183f..03a5b32 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -45,6 +45,7 @@ struct object_symbol {
char *name;
int type, bind;
int sec_index;
+ unsigned long kaddr;
};
struct export_symbol {
@@ -284,6 +285,57 @@ static void symtab_read(struct lookup_table *table, char *path)
fclose(file);
}
+static void ksymtab_read(struct lookup_table *table, char *path)
+{
+ FILE *file;
+ struct object_symbol *sym, *sym1, *sym2;
+ unsigned long value;
+ int i, j, idx;
+ char line[256], name[256], type[256], mod[256];
+
+ idx = 0;
+ file = fopen(path, "r");
+ if (file == NULL)
+ ERROR("fopen");
+
+ while (fgets(line, 256, file)) {
+ if (sscanf(line, "%lx %s %s [%s]\n",
+ &value, type, name, mod) != 4)
+ continue;
+
+ if (name[0] == '$')
+ continue;
+
+ i = idx;
+ for_each_obj_symbol_continue(i, sym, table) {
+ if (!strncmp(sym->name, name, KSYM_NAME_LEN-1)) {
+ sym->kaddr = value;
+ idx = i + 1;
+ break;
+ }
+ }
+ }
+
+ for_each_obj_symbol(i, sym1, table) {
+ if (sym1->kaddr == 0)
+ continue;
+ for_each_obj_symbol(j, sym2, table) {
+ if (sym2->kaddr == 0)
+ continue;
+ if (sym1 == sym2)
+ continue;
+ if (sym1->sec_index != sym2->sec_index)
+ continue;
+ if ((long)sym1->value - (long)sym2->value ==
+ (long)sym1->kaddr - (long)sym2->kaddr)
+ continue;
+
+ ERROR("base mismatch(symbol offset)");
+ }
+ }
+ fclose(file);
+}
+
/*
* Symvers file format is the following for kernels v5.3 and newer:
* <CRC> <Symbol> <Namespace> <Module> <Export Type>
@@ -352,7 +404,8 @@ static void symvers_read(struct lookup_table *table, char *path)
}
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
- char *hint, struct sym_compare_type *locals)
+ char *hint, struct sym_compare_type *locals,
+ char *kallsyms)
{
struct lookup_table *table;
@@ -363,6 +416,8 @@ struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
symtab_read(table, symtab_path);
symvers_read(table, symvers_path);
+ if (kallsyms)
+ ksymtab_read(table, kallsyms);
find_local_syms(table, hint, locals);
return table;
@@ -609,6 +664,23 @@ int lookup_ref_symbol_offset(struct lookup_table *table, char *name,
}
}
+ if (orig_sym->kaddr == 0)
+ return 1;
+
+ /*find a unique symbol has kaddr*/
+ for_each_obj_symbol(i, sym, table) {
+ if (!strcmp(sym->name, name) || sym->type == STT_FILE ||
+ sym->kaddr == 0 || strchr(sym->name, '.'))
+ continue;
+
+ if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
+ refsym->name = sym->name;
+ refsym->value = 0;
+ *offset = (long)orig_sym->kaddr - (long)sym->kaddr;
+ return 0;
+ }
+ }
+
return 1;
}
diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h
index 6f640fd..daeea73 100644
--- a/kpatch-build/lookup.h
+++ b/kpatch-build/lookup.h
@@ -23,7 +23,8 @@ struct lookup_refsym {
};
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
- char *hint, struct sym_compare_type *locals);
+ char *hint, struct sym_compare_type *locals,
+ char *kallsyms);
void lookup_close(struct lookup_table *table);
int lookup_local_symbol(struct lookup_table *table, char *name,
struct lookup_result *result);
--
2.18.1

View File

@ -0,0 +1,154 @@
From 88d2a5c88fcab0016db9347fbab41a22b9fb9a52 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 20:43:34 -0500
Subject: [PATCH 13/24] livepatch-patch-hook: support force enable/disable
we use force to indicate function which bypass stack check
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/kpatch-patch.h | 1 +
kmod/patch/livepatch-patch-hook.c | 17 +++++++++++++++++
kpatch-build/kpatch-build | 24 ++++++++++++++++++++----
3 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h
index 9df7818..6e39364 100644
--- a/kmod/patch/kpatch-patch.h
+++ b/kmod/patch/kpatch-patch.h
@@ -64,4 +64,5 @@ struct kpatch_post_unpatch_callback {
char *objname;
};
+extern unsigned long __kpatch_force_funcs[], __kpatch_force_funcs_end[];
#endif /* _KPATCH_PATCH_H_ */
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index b578ef3..71439d9 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -432,6 +432,16 @@ extern struct kpatch_patch_func __kpatch_funcs[], __kpatch_funcs_end[];
extern struct kpatch_patch_dynrela __kpatch_dynrelas[], __kpatch_dynrelas_end[];
#endif
+static int patch_is_func_forced(unsigned long addr)
+{
+ unsigned long *a;
+
+ for (a = __kpatch_force_funcs; a < __kpatch_force_funcs_end; a++)
+ if (*a == addr)
+ return 1;
+ return 0;
+}
+
static int __init patch_init(void)
{
struct kpatch_patch_func *kfunc;
@@ -520,6 +530,13 @@ static int __init patch_init(void)
lfunc = &lfuncs[j];
lfunc->old_name = func->kfunc->name;
lfunc->new_func = (void *)func->kfunc->new_addr;
+#if defined(__KLP_SUPPORT_FORCE__)
+#ifdef __ALL_FORCE__
+ lfunc->force = 1;
+#else
+ lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
+#endif
+#endif
#ifdef HAVE_SYMPOS
lfunc->old_sympos = func->kfunc->sympos;
#else
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 722d362..9a98bfc 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -383,28 +383,32 @@ find_special_section_data_aarch64() {
# shellcheck disable=SC2086
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data $AWK_OPTIONS '
- BEGIN { a = b = e = j = 0 }
+ BEGIN { a = b = e = j = c = f = 0 }
# Set state if name matches
a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
+ c == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {c = 1; next}
# Reset state unless this abbrev describes the struct size
a == 1 && !/DW_AT_byte_size/ { a = 0; next }
b == 1 && !/DW_AT_byte_size/ { b = 0; next }
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
j == 1 && !/DW_AT_byte_size/ { j = 0; next }
+ c == 1 && /DW_TAG_structure_type/ { c = 3; next }
+ c == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
# Now that we know the size, stop parsing for it
a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2}
e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
+ f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
# Bail out once we have everything
- a == 2 && b == 2 && e == 2 && (j == 2 || skip_j) {exit}')"
+ a == 2 && b == 2 && e == 2 && (j == 2 || skip_j) && c == 3 {exit}')"
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
@@ -437,7 +441,7 @@ find_special_section_data() {
# shellcheck disable=SC2086
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data $AWK_OPTIONS '
- BEGIN { a = b = p = e = o = j = s = i = 0 }
+ BEGIN { a = b = p = e = o = j = s = i = c = f = 0 }
# Set state if name matches
a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
@@ -448,6 +452,7 @@ find_special_section_data() {
j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
s == 0 && /DW_AT_name.* static_call_site[[:space:]]*$/ {s = 1; next}
i == 0 && /DW_AT_name.* pi_entry[[:space:]]*$/ {i = 1; next}
+ c == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {c = 1; next}
# Reset state unless this abbrev describes the struct size
a == 1 && !/DW_AT_byte_size/ { a = 0; next }
@@ -458,6 +463,8 @@ find_special_section_data() {
j == 1 && !/DW_AT_byte_size/ { j = 0; next }
s == 1 && !/DW_AT_byte_size/ { s = 0; next }
i == 1 && !/DW_AT_byte_size/ { i = 0; next }
+ c == 1 && /DW_TAG_structure_type/ { c = 3; next }
+ c == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
# Now that we know the size, stop parsing for it
a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
@@ -468,9 +475,10 @@ find_special_section_data() {
j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
s == 1 {printf("export STATIC_CALL_STRUCT_SIZE=%d\n", $4); s = 2}
i == 1 {printf("export PRINTK_INDEX_STRUCT_SIZE=%d\n", $4); i = 2}
+ f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
# Bail out once we have everything
- a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && (j == 2 || skip_j) && (s == 2 || skip_s) && (i == 2 || skip_i) {exit}')"
+ a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && (j == 2 || skip_j) && (s == 2 || skip_s) && (i == 2 || skip_i) && c == 3 {exit}')"
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
@@ -1231,6 +1239,14 @@ if [[ -n "$DISABLE_AFTER_LOAD" ]];then
export KCPPFLAGS="-DDISABLE_AFTER_LOAD $KCPPFLAGS"
fi
+if [[ -n "$NO_STACK_CHECK" ]];then
+ export KCPPFLAGS="-D__ALL_FORCE__ $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_FORCE" ]];then
+ export KCPPFLAGS="-D__KLP_SUPPORT_FORCE__ $KCPPFLAGS"
+fi
+
save_env
echo "Building patch module: $MODNAME.ko"
--
2.23.0

View File

@ -1,7 +1,7 @@
From 48fef6d7eceb336816e45690d43093f8be919315 Mon Sep 17 00:00:00 2001 From d28c18b094c18118427eadb4c63ab73cf64af4e6 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 21:01:02 -0500 Date: Wed, 26 Feb 2020 21:01:02 -0500
Subject: [PATCH 15/23] kpatch-build: ignore debuginfo in patch Subject: [PATCH 14/24] kpatch-build: ignore debuginfo in patch
Just ignore all .debug_* sections Just ignore all .debug_* sections
@ -12,10 +12,10 @@ Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
2 files changed, 19 insertions(+) 2 files changed, 19 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index c5320d4..bc3685b 100644 index ea1e01b..8c5af6b 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -2414,6 +2414,23 @@ static void kpatch_include_debug_sections(struct kpatch_elf *kelf) @@ -2714,6 +2714,23 @@ static void kpatch_include_debug_sections(struct kpatch_elf *kelf)
} }
} }
@ -39,26 +39,26 @@ index c5320d4..bc3685b 100644
static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf) static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf)
{ {
struct section *sec, *strsec, *ignoresec; struct section *sec, *strsec, *ignoresec;
@@ -3682,6 +3699,7 @@ int main(int argc, char *argv[]) @@ -3908,6 +3925,7 @@ int main(int argc, char *argv[])
new_globals_exist = kpatch_include_new_globals(kelf_patched); new_globals_exist = kpatch_include_new_globals(kelf_patched);
kpatch_include_new_static_var(kelf_patched); kpatch_include_new_static_var(kelf_patched);
kpatch_include_debug_sections(kelf_patched); kpatch_include_debug_sections(kelf_patched);
+ kpatch_ignore_debug_sections(kelf_patched); + kpatch_ignore_debug_sections(kelf_patched);
kpatch_process_special_sections(kelf_patched); kpatch_process_special_sections(kelf_patched, lookup);
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 57487b1..c109ee3 100755 index 9a98bfc..a0d8ba8 100755
--- a/kpatch-build/kpatch-build --- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build
@@ -1143,6 +1143,7 @@ KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \ @@ -1295,6 +1295,7 @@ KPATCH_LDFLAGS="$KPATCH_LDFLAGS"
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \ save_env
CROSS_COMPILE="$ARCH_COMPILE" \
make 2>&1 | logger || die
+${ARCH_COMPILE}strip -g "$TEMPDIR/patch/$MODNAME.ko"
if ! "$KPATCH_MODULE"; then make "${MAKEVARS[@]}" 2>&1 | logger || die
if [[ -z "$KPATCH_LDFLAGS" ]]; then +strip -g "$TEMPDIR/patch/$MODNAME.ko"
if [[ "$USE_KLP" -eq 1 ]]; then
if [[ "$USE_KLP_ARCH" -eq 0 ]]; then
-- --
2.18.1 2.23.0

View File

@ -1,78 +0,0 @@
From 62e9cb43c324c933b2934ce9d2923097b96dab1e Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 20:43:34 -0500
Subject: [PATCH 14/23] livepatch-patch-hook: support force enable/disable
we use force to indicate function which bypass stack check
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/kpatch-patch.h | 1 +
kmod/patch/livepatch-patch-hook.c | 18 ++++++++++++++++++
kpatch-build/kpatch-build | 4 ++++
3 files changed, 23 insertions(+)
diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h
index 9df7818..6e39364 100644
--- a/kmod/patch/kpatch-patch.h
+++ b/kmod/patch/kpatch-patch.h
@@ -64,4 +64,5 @@ struct kpatch_post_unpatch_callback {
char *objname;
};
+extern unsigned long __kpatch_force_funcs[], __kpatch_force_funcs_end[];
#endif /* _KPATCH_PATCH_H_ */
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index fb23a94..5a0de7f 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -239,6 +239,17 @@ extern struct kpatch_post_patch_callback __kpatch_callbacks_post_patch[], __kpat
extern struct kpatch_pre_unpatch_callback __kpatch_callbacks_pre_unpatch[], __kpatch_callbacks_pre_unpatch_end[];
extern struct kpatch_post_unpatch_callback __kpatch_callbacks_post_unpatch[], __kpatch_callbacks_post_unpatch_end[];
+static int patch_is_func_forced(unsigned long addr)
+{
+ unsigned long *a;
+
+ for (a = __kpatch_force_funcs; a < __kpatch_force_funcs_end; a++)
+ if (*a == addr)
+ return 1;
+ return 0;
+}
+
+
#ifdef HAVE_CALLBACKS
static int add_callbacks_to_patch_objects(void)
{
@@ -403,6 +414,13 @@ static int __init patch_init(void)
lfunc = &lfuncs[j];
lfunc->old_name = func->kfunc->name;
lfunc->new_func = (void *)func->kfunc->new_addr;
+#if defined(__KLP_SUPPORT_FORCE__)
+#ifdef __ALL_FORCE__
+ lfunc->force = 1;
+#else
+ lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
+#endif
+#endif
#ifdef HAVE_SYMPOS
lfunc->old_sympos = func->kfunc->sympos;
#else
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 8bef7fb..57487b1 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -1079,6 +1079,10 @@ if "$KPATCH_MODULE"; then
export KCPPFLAGS="-D__KPATCH_MODULE__"
fi
+if [[ -n "$NO_STACK_CHECK" ]];then
+ export KCPPFLAGS="-D__ALL_FORCE__ $KCPPFLAGS"
+fi
+
if [[ -n "$KLP_SUPPORT_FORCE" ]];then
export KCPPFLAGS="-D__KLP_SUPPORT_FORCE__ $KCPPFLAGS"
fi
--
2.18.1

View File

@ -1,7 +1,7 @@
From 24392c6f62e26afb192992808772bd19ceab5446 Mon Sep 17 00:00:00 2001 From 8341b9ea6b889a887577772f6adfb49e1fea1bc1 Mon Sep 17 00:00:00 2001
From: Bin Yang <robin.yb@huawei.com> From: Bin Yang <robin.yb@huawei.com>
Date: Tue, 16 Jul 2019 14:39:27 +0800 Date: Tue, 16 Jul 2019 14:39:27 +0800
Subject: [PATCH 16/23] add object in kpatch Subject: [PATCH 15/24] add object in kpatch
it is required by make_hotpatch users it is required by make_hotpatch users
@ -11,10 +11,10 @@ Signed-off-by: Bin Yang <robin.yb@huawei.com>
1 file changed, 3 insertions(+) 1 file changed, 3 insertions(+)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index c109ee3..de448dc 100755 index a0d8ba8..c21f3ca 100755
--- a/kpatch-build/kpatch-build --- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build
@@ -1071,6 +1071,8 @@ echo -n "Patched objects:" @@ -1227,6 +1227,8 @@ echo -n "Patched objects:"
for i in $(echo "${objnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ') for i in $(echo "${objnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')
do do
echo -n " $i" echo -n " $i"
@ -23,14 +23,14 @@ index c109ee3..de448dc 100755
done done
echo echo
@@ -1177,6 +1179,7 @@ UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \ @@ -1353,6 +1355,7 @@ UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \
[[ -z "$USERMODBUILDDIR" ]] && [[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED" [[ -z "$USERMODBUILDDIR" ]] && [[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die
+cp -f "$TEMPDIR/patch/object" "$BASE" || die +cp -f "$TEMPDIR/patch/object" "$BASE" || die
[[ "$DEBUG" -eq 0 ]] && rm -f "$LOGFILE" [[ "$DEBUG" -eq 0 && "$SKIPCLEANUP" -eq 0 ]] && rm -f "$LOGFILE"
-- --
2.18.1 2.23.0

View File

@ -1,7 +1,7 @@
From a1d89dc3ab47d443e879d4553a9ff80e8b82a3ab Mon Sep 17 00:00:00 2001 From 2dab7f74fecefab38fbd9c2d171e5a6090e66829 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 27 Feb 2020 15:36:55 -0500 Date: Thu, 27 Feb 2020 15:36:55 -0500
Subject: [PATCH 17/23] create-diff-object: fix .orc_unwind_ip error Subject: [PATCH 16/24] create-diff-object: fix .orc_unwind_ip error
error: .orc_unwind_ip section header details error: .orc_unwind_ip section header details
differ from .orc_unwind_ip differ from .orc_unwind_ip
@ -14,29 +14,29 @@ Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
1 file changed, 6 insertions(+) 1 file changed, 6 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index bc3685b..20213a0 100644 index 8c5af6b..5f51034 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -975,6 +975,9 @@ static void kpatch_correlate_sections(struct list_head *seclist1, struct list_he @@ -1079,6 +1079,9 @@ static void kpatch_correlate_sections(struct list_head *seclist_orig,
continue; continue;
} }
+ if (strstr(sec1->name, ".orc_unwind")) + if (strstr(sec_orig->name, ".orc_unwind"))
+ continue; + continue;
+ +
kpatch_correlate_section(sec1, sec2); kpatch_correlate_section(sec_orig, sec_patched);
break; break;
} }
@@ -1020,6 +1023,9 @@ static void kpatch_correlate_symbols(struct list_head *symlist1, struct list_hea @@ -1125,6 +1128,9 @@ static void kpatch_correlate_symbols(struct list_head *symlist_orig,
sym1->sec->twin != sym2->sec) sym_orig->sec->twin != sym_patched->sec)
continue; continue;
+ if (strstr(sym1->name, ".orc_unwind")) + if (strstr(sym_orig->name, ".orc_unwind"))
+ continue; + continue;
+ +
kpatch_correlate_symbol(sym1, sym2); kpatch_correlate_symbol(sym_orig, sym_patched);
break; break;
} }
-- --
2.18.1 2.23.0

View File

@ -0,0 +1,67 @@
From 78a04dd5a2a98e6442441b802e1f4aa017fae87a Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Mon, 2 Mar 2020 04:35:07 -0500
Subject: [PATCH 17/24] create-diff-object: add jump label support
This patch processes the __jump_table special section, and
only the jump_lable used by the changed functions will be
included in __jump_table section and solve this limitation.
(The livepatch in kernel should also be modified that processing
the tracepoint again after the dynamic relocation by livepatch.)
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 5f51034..6b915ae 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -79,6 +79,7 @@ enum subsection {
enum loglevel loglevel = NORMAL;
bool KLP_ARCH;
+char *KEEP_JUMP_LABEL = NULL;
/*******************
* Data structures
@@ -2374,6 +2375,8 @@ static bool should_keep_jump_label(struct lookup_table *lookup,
if (tracepoint || dynamic_debug)
return false;
+ if (KEEP_JUMP_LABEL)
+ return true;
/*
* This will be upgraded to an error after all jump labels have
* been reported.
@@ -2404,6 +2407,8 @@ static bool should_keep_jump_label(struct lookup_table *lookup,
if (tracepoint || dynamic_debug)
return false;
+ if (KEEP_JUMP_LABEL)
+ return true;
/*
* This will be upgraded to an error after all jump labels have
* been reported.
@@ -2972,8 +2977,7 @@ static void kpatch_process_special_sections(struct kpatch_elf *kelf,
* labels and enable tracepoints in a patched function.
*/
list_for_each_entry(sec, &kelf->sections, list) {
- if (strcmp(sec->name, "__jump_table") &&
- strcmp(sec->name, "__tracepoints") &&
+ if (strcmp(sec->name, "__tracepoints") &&
strcmp(sec->name, "__tracepoints_ptrs") &&
strcmp(sec->name, "__tracepoints_strings"))
continue;
@@ -3865,6 +3869,7 @@ int main(int argc, char *argv[])
char *parent_symtab, *mod_symvers, *patch_name, *output_obj;
char *no_profiling_calls = NULL;
+ KEEP_JUMP_LABEL = getenv("KEEP_JUMP_LABEL");
memset(&arguments, 0, sizeof(arguments));
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
if (arguments.debug)
--
2.23.0

View File

@ -1,7 +1,7 @@
From 586dcb3d2ccd8e45c78d3d140f0190ab5a78ecb3 Mon Sep 17 00:00:00 2001 From 46a24818a2227ad1b6f644c2499415021522ce55 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 12 Mar 2020 06:56:21 -0400 Date: Thu, 12 Mar 2020 06:56:21 -0400
Subject: [PATCH 20/23] kpatch-build: add compile flag -fno-reorder-functions Subject: [PATCH 18/24] kpatch-build: add compile flag -fno-reorder-functions
Sometimes function foo with static variables can be put in Sometimes function foo with static variables can be put in
.text.foo section in original binary and be put in .text.foo section in original binary and be put in
@ -23,18 +23,18 @@ Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
1 file changed, 1 insertion(+), 1 deletion(-) 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index de448dc..ad7ab71 100755 index c21f3ca..2ead6e4 100755
--- a/kpatch-build/kpatch-build --- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build
@@ -887,7 +887,7 @@ if [[ "$ARCH" = "ppc64le" ]]; then @@ -994,7 +994,7 @@ if [[ "$ARCH" = "ppc64le" ]]; then
ARCH_KCFLAGS="-mcmodel=large -fplugin=$PLUGINDIR/ppc64le-plugin.so" ARCH_KCFLAGS="-mcmodel=large -fplugin=$PLUGINDIR/ppc64le-plugin.so"
fi fi
-export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections \ -export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections \
+export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections -fno-reorder-functions \ +export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections -fno-reorder-functions \
$ARCH_KCFLAGS $DEBUG_KCFLAGS ${GCC_ADD_OPTION}" $ARCH_KCFLAGS $DEBUG_KCFLAGS"
echo "Reading special section data" echo "Reading special section data"
-- --
2.18.1 2.23.0

View File

@ -1,33 +0,0 @@
From f162056f0448e676345e3205ef4b190f81b51295 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 12 Mar 2020 05:10:55 -0400
Subject: [PATCH 18/23] use original reloc for symbols from modules
symbols exported in a patch will generate a symbol version with
object module name in Module.symvers, but the symbol is actually
in patch module which cause livepatch symbol lookup failed.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 20213a0..457d517 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -3141,10 +3141,8 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
if (!strcmp(sym_objname, "vmlinux"))
continue;
- if (!strcmp(sym_objname, objname))
- continue;
-
external = 1;
+ continue;
}
}
log_debug("lookup for %s @ 0x%016lx len %lu\n",
--
2.18.1

View File

@ -1,7 +1,8 @@
From 737ab3efcde45cde5fbe43ee977fc18b6912f356 Mon Sep 17 00:00:00 2001 From 47a9749d381f02868b4f4bbe1bc841f3f38ac1a1 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Sun, 22 Nov 2020 21:40:39 +0800 Date: Sun, 22 Nov 2020 21:40:39 +0800
Subject: [PATCH] Fix relocation not resolved when new functions exported only Subject: [PATCH 19/24] Fix relocation not resolved when new functions exported
only
When no functions changed and new functions exported, kobject is not When no functions changed and new functions exported, kobject is not
created, so livepatch will not call klp_init_object and relocation created, so livepatch will not call klp_init_object and relocation
@ -12,8 +13,8 @@ Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
kmod/patch/kpatch-patch.h | 4 ++++ kmod/patch/kpatch-patch.h | 4 ++++
kmod/patch/kpatch.lds.S | 6 ++++++ kmod/patch/kpatch.lds.S | 6 ++++++
kmod/patch/livepatch-patch-hook.c | 19 +++++++++++++++++++ kmod/patch/livepatch-patch-hook.c | 19 +++++++++++++++++++
kpatch-build/create-diff-object.c | 24 ++++++++++++++++++++++++ kpatch-build/create-diff-object.c | 26 ++++++++++++++++++++++++++
4 files changed, 53 insertions(+) 4 files changed, 55 insertions(+)
diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h
index 6e39364..33f2056 100644 index 6e39364..33f2056 100644
@ -46,10 +47,10 @@ index bc5de82..4c4d77b 100644
+ } + }
} }
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index 5a0de7f..d3fb1db 100644 index 71439d9..9e56fe3 100644
--- a/kmod/patch/livepatch-patch-hook.c --- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c +++ b/kmod/patch/livepatch-patch-hook.c
@@ -249,6 +249,22 @@ static int patch_is_func_forced(unsigned long addr) @@ -442,6 +442,22 @@ static int patch_is_func_forced(unsigned long addr)
return 0; return 0;
} }
@ -69,10 +70,10 @@ index 5a0de7f..d3fb1db 100644
+ return 0; + return 0;
+} +}
+ +
static int __init patch_init(void)
#ifdef HAVE_CALLBACKS {
static int add_callbacks_to_patch_objects(void) struct kpatch_patch_func *kfunc;
@@ -382,6 +398,9 @@ static int __init patch_init(void) @@ -485,6 +501,9 @@ static int __init patch_init(void)
if (ret) if (ret)
goto out; goto out;
@ -83,10 +84,10 @@ index 5a0de7f..d3fb1db 100644
ret = -ENOMEM; ret = -ENOMEM;
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index fca68b8..bea758e 100644 index 6b915ae..0bef022 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -2553,6 +2553,27 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj @@ -2916,6 +2916,27 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj
karch_sec->sh.sh_size = karch_sec->data->d_size; karch_sec->sh.sh_size = karch_sec->data->d_size;
} }
@ -106,24 +107,26 @@ index fca68b8..bea758e 100644
+ /* entries[index].objname */ + /* entries[index].objname */
+ ALLOC_LINK(rela, &kobj_sec->rela->relas); + ALLOC_LINK(rela, &kobj_sec->rela->relas);
+ rela->sym = strsym; + rela->sym = strsym;
+ rela->type = absolute_rela_type; + rela->type = ABSOLUTE_RELA_TYPE;
+ rela->addend = offset_of_string(&kelf->strings, objname); + rela->addend = offset_of_string(&kelf->strings, objname);
+ rela->offset = (unsigned int)(offsetof(struct kpatch_object, objname)); + rela->offset = (unsigned int)(offsetof(struct kpatch_object, objname));
+} +}
+ +
static void kpatch_process_special_sections(struct kpatch_elf *kelf) static void kpatch_process_special_sections(struct kpatch_elf *kelf,
struct lookup_table *lookup)
{ {
struct special_section *special; @@ -3973,6 +3994,11 @@ int main(int argc, char *argv[])
@@ -3710,6 +3731,9 @@ int main(int argc, char *argv[])
kpatch_create_intermediate_sections(kelf_out, lookup, parent_name, patch_name); kpatch_create_intermediate_sections(kelf_out, lookup, parent_name, patch_name);
kpatch_create_kpatch_arch_section(kelf_out, parent_name); kpatch_create_kpatch_arch_section(kelf_out, parent_name);
kpatch_create_callbacks_objname_rela(kelf_out, parent_name); kpatch_create_callbacks_objname_rela(kelf_out, parent_name);
+
+ if (!num_changed && new_globals_exist) { + if (!num_changed && new_globals_exist) {
+ kpatch_create_kpatch_object_section(kelf_out, parent_name); + kpatch_create_kpatch_object_section(kelf_out, parent_name);
+ } + }
+
kpatch_build_strings_section_data(kelf_out); kpatch_build_strings_section_data(kelf_out);
gcc_add_option = getenv("GCC_ADD_OPTION"); kpatch_create_mcount_sections(kelf_out);
-- --
2.18.1 2.23.0

View File

@ -1,91 +0,0 @@
From c0b20224cf1b081fba152cb4944d762515561d89 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Mon, 2 Mar 2020 04:35:07 -0500
Subject: [PATCH 19/23] create-diff-object: add jump label support
This patch processes the __jump_table special section, and
only the jump_lable used by the changed functions will be
included in __jump_table section and solve this limitation.
(The livepatch in kernel should also be modified that processing
the tracepoint again after the dynamic relocation by livepatch.)
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 47 +------------------------------
1 file changed, 1 insertion(+), 46 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 457d517..4fa4488 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2140,7 +2140,6 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf,
struct rela *rela, *safe;
char *src, *dest;
unsigned int group_size, src_offset, dest_offset, include;
- int jump_table = !strcmp(special->name, "__jump_table");
LIST_HEAD(newrelas);
@@ -2180,49 +2179,6 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf,
if (!include)
continue;
- /*
- * Jump labels (aka static keys or static branches) aren't
- * actually supported for the time being. Warn on all
- * non-tracepoint jump labels when they occur in a replacement
- * function. An inert tracepoint is harmless enough, but a
- * broken static key can cause unexpected behavior.
- *
- * Here we hard-code knowledge about the contents of the
- * jump_label struct. It has three fields: code, target, and
- * key.
- */
- if (jump_table) {
- struct rela *code, *key;
- int i = 0;
-
- list_for_each_entry(rela, &sec->relas, list) {
- if (rela->offset >= src_offset &&
- rela->offset < src_offset + group_size) {
- if (i == 0)
- code = rela;
- else if (i == 2)
- key = rela;
- i++;
- }
- }
-
- if (i != 3)
- ERROR("BUG: __jump_table has an unexpected format");
-
- /* inert tracepoints are harmless */
- if (!strncmp(key->sym->name, "__tracepoint_", 13))
- continue;
-
- /* inert dynamic debug printks are harmless */
- if (is_dynamic_debug_symbol(key->sym))
- continue;
-
- ERROR("Found a jump label at %s()+0x%lx, using key %s. Jump labels aren't currently supported. Use static_key_enabled() instead.",
- code->sym->name, code->addend, key->sym->name);
-
- continue;
- }
-
/*
* Copy all relas in the group. It's possible that the relas
* aren't sorted (e.g. .rela.fixup), so go through the entire
@@ -2659,8 +2615,7 @@ static void kpatch_process_special_sections(struct kpatch_elf *kelf)
* jump labels and enable tracepoints in a patched function.
*/
list_for_each_entry(sec, &kelf->sections, list) {
- if (strcmp(sec->name, "__jump_table") &&
- strcmp(sec->name, "__tracepoints") &&
+ if (strcmp(sec->name, "__tracepoints") &&
strcmp(sec->name, "__tracepoints_ptrs") &&
strcmp(sec->name, "__tracepoints_strings"))
continue;
--
2.18.1

View File

@ -1,7 +1,8 @@
From 0e08aa99583573953367d5c1ec21901325c7faee Mon Sep 17 00:00:00 2001 From a81f64c1eae14f2b0da8168ca60b3d9beb0a9fb0 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 30 Dec 2020 21:13:10 -0500 Date: Wed, 30 Dec 2020 21:13:10 -0500
Subject: [PATCH] support remove static variables using KPATCH_IGNORE_STATIC Subject: [PATCH 20/24] support remove static variables using
KPATCH_IGNORE_STATIC
Static variables will be removed due to compiler optimization. Static variables will be removed due to compiler optimization.
And some static variables can be treated as new variables, such as And some static variables can be treated as new variables, such as
@ -10,30 +11,31 @@ to tell kpatch to treat the static variables as new variables.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com> Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
--- ---
kmod/patch/kpatch-macros.h | 3 +++ kmod/patch/kpatch-macros.h | 4 +++
kpatch-build/create-diff-object.c | 45 ++++++++++++++++++++++++++++++- kpatch-build/create-diff-object.c | 45 ++++++++++++++++++++++++++++++-
2 files changed, 47 insertions(+), 1 deletion(-) 2 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/kmod/patch/kpatch-macros.h b/kmod/patch/kpatch-macros.h diff --git a/kmod/patch/kpatch-macros.h b/kmod/patch/kpatch-macros.h
index a60a267..9a30d68 100644 index caaadbc..ee455d2 100644
--- a/kmod/patch/kpatch-macros.h --- a/kmod/patch/kpatch-macros.h
+++ b/kmod/patch/kpatch-macros.h +++ b/kmod/patch/kpatch-macros.h
@@ -5,6 +5,9 @@ @@ -12,6 +12,10 @@
#include <linux/jiffies.h> # define __kpatch_section(section) __section(#section)
#include <linux/version.h> #endif
+#define KPATCH_IGNORE_STATIC(_static) \ +#define KPATCH_IGNORE_STATIC(_static) \
+ char *__UNIQUE_ID(kpatch_ignore_static_) __section(.kpatch.ignore.statics) = _static; + char *__UNIQUE_ID(kpatch_ignore_static_) __section(.kpatch.ignore.statics) = _static;
+
+ +
/* /*
* KPATCH_IGNORE_SECTION macro * KPATCH_IGNORE_SECTION macro
* *
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index a2a9cab..211ea72 100644 index 0bef022..f83000b 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -1151,6 +1151,40 @@ static int kpatch_is_normal_static_local(struct symbol *sym) @@ -1345,6 +1345,40 @@ static struct rela *kpatch_find_static_twin_ref(struct section *rela_sec, struct
return 1; return NULL;
} }
+static int kpatch_mark_ignored_statics(struct kpatch_elf *kelf, struct symbol *sym) +static int kpatch_mark_ignored_statics(struct kpatch_elf *kelf, struct symbol *sym)
@ -73,7 +75,7 @@ index a2a9cab..211ea72 100644
/* /*
* gcc renames static local variables by appending a period and a number. For * gcc renames static local variables by appending a period and a number. For
* example, __foo could be renamed to __foo.31452. Unfortunately this number * example, __foo could be renamed to __foo.31452. Unfortunately this number
@@ -1230,6 +1264,11 @@ static void kpatch_correlate_static_local_variables(struct kpatch_elf *base, @@ -1425,6 +1459,11 @@ static void kpatch_correlate_static_local_variables(struct kpatch_elf *orig,
if (sym->twin) if (sym->twin)
continue; continue;
@ -85,7 +87,7 @@ index a2a9cab..211ea72 100644
bundled = sym == sym->sec->sym; bundled = sym == sym->sec->sym;
if (bundled && sym->sec == sec->base) { if (bundled && sym->sec == sec->base) {
/* /*
@@ -1286,6 +1325,11 @@ static void kpatch_correlate_static_local_variables(struct kpatch_elf *base, @@ -1482,6 +1521,11 @@ static void kpatch_correlate_static_local_variables(struct kpatch_elf *orig,
if (!kpatch_is_normal_static_local(sym)) if (!kpatch_is_normal_static_local(sym))
continue; continue;
@ -94,10 +96,10 @@ index a2a9cab..211ea72 100644
+ continue; + continue;
+ } + }
+ +
if (!sym->twin || !sec->twin) if (!sec->twin && sec->base->sym) {
DIFF_FATAL("reference to static local variable %s in %s was removed", struct symbol *parent = NULL;
sym->name,
@@ -1329,7 +1373,6 @@ static void kpatch_correlate_static_local_variables(struct kpatch_elf *base, @@ -1525,7 +1569,6 @@ static void kpatch_correlate_static_local_variables(struct kpatch_elf *orig,
log_normal("WARNING: unable to correlate static local variable %s used by %s, assuming variable is new\n", log_normal("WARNING: unable to correlate static local variable %s used by %s, assuming variable is new\n",
sym->name, sym->name,
kpatch_section_function_name(sec)); kpatch_section_function_name(sec));
@ -106,5 +108,5 @@ index a2a9cab..211ea72 100644
} }
} }
-- --
2.18.1 2.23.0

View File

@ -1,7 +1,8 @@
From 8d1e6f4cfe3fc7007f17e0f01e7ec8aa71e18cae Mon Sep 17 00:00:00 2001 From 2189dd022cda1973efdc198daa0525cbd2ee5bb2 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 17 Sep 2021 10:22:24 +0800 Date: Fri, 17 Sep 2021 10:22:24 +0800
Subject: [PATCH] create-diff-object: fix segment fault when sec2->rela is NULL Subject: [PATCH 21/24] create-diff-object: fix segment fault when sec2->rela
is NULL
when patched section has no rela section, we meet segment fault in when patched section has no rela section, we meet segment fault in
__kpatch_correlate_section. add sec2->rela check to fix it. __kpatch_correlate_section. add sec2->rela check to fix it.
@ -13,18 +14,18 @@ Signed-off-by: hubin57 <hubin57@huawei.com>
1 file changed, 1 insertion(+), 1 deletion(-) 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index ff2b0e4..2159cf0 100644 index f83000b..aa5c5c4 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -916,7 +916,7 @@ static void kpatch_correlate_section(struct section *sec1, struct section *sec2) @@ -1015,7 +1015,7 @@ static void kpatch_correlate_section(struct section *sec_orig,
__kpatch_correlate_section(sec1->base, sec2->base); __kpatch_correlate_section(sec_orig->base, sec_patched->base);
sec1 = sec1->base; sec_orig = sec_orig->base;
sec2 = sec2->base; sec_patched = sec_patched->base;
- } else if (sec1->rela) { - } else if (sec_orig->rela) {
+ } else if (sec1->rela && sec2->rela) { + } else if (sec_orig->rela && sec_patched->rela) {
__kpatch_correlate_section(sec1->rela, sec2->rela); __kpatch_correlate_section(sec_orig->rela, sec_patched->rela);
} }
-- --
2.27.0 2.23.0

View File

@ -1,28 +0,0 @@
From cff73a8dca7069d9e558c65f0b76297feab09719 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 12 Mar 2020 07:37:00 -0400
Subject: [PATCH 21/23] kpatch-build: don't copy .config for out of tree module
.config only need to be restored when the build patch for kernel
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index ad7ab71..fd34812 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -828,7 +828,7 @@ fi
[[ -z "$CONFIGFILE" ]] && CONFIGFILE="$SRCDIR"/.config
[[ ! -e "$CONFIGFILE" ]] && die "can't find config file"
-[[ ! "$CONFIGFILE" -ef "$SRCDIR"/.config ]] && cp -f "$CONFIGFILE" "$SRCDIR/.config"
+[[ -z "$OOT_MODULE" ]] && [[ ! "$CONFIGFILE" -ef "$SRCDIR"/.config ]] && cp -f "$CONFIGFILE" "$SRCDIR/.config"
# Build variables - Set some defaults, then adjust features
# according to .config and kernel version
--
2.18.1

View File

@ -1,58 +0,0 @@
From 11e57aa03ae87fa24028800851f34205a2aeb0d8 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 15 Apr 2020 06:37:59 -0400
Subject: [PATCH 22/23] support force enable/disable for x86
detect if the klp_func structure in vmlinux have force
member, if it has, export KLP_SUPPORT_FORCE=y.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index fd34812..523d5df 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -373,7 +373,7 @@ find_special_section_data() {
# shellcheck disable=SC2086
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data $AWK_OPTIONS '
- BEGIN { a = b = p = e = o = j = 0 }
+ BEGIN { a = b = p = e = o = j = c = f = 0 }
# Set state if name matches
a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
@@ -382,6 +382,7 @@ find_special_section_data() {
e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
o == 0 && /DW_AT_name.* orc_entry[[:space:]]*$/ {o = 1; next}
j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
+ c == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {c = 1; next}
# Reset state unless this abbrev describes the struct size
a == 1 && !/DW_AT_byte_size/ { a = 0; next }
@@ -390,6 +391,8 @@ find_special_section_data() {
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
o == 1 && !/DW_AT_byte_size/ { o = 0; next }
j == 1 && !/DW_AT_byte_size/ { j = 0; next }
+ c == 1 && /DW_TAG_structure_type/ { c = 3; next }
+ c == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
# Now that we know the size, stop parsing for it
a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
@@ -398,9 +401,10 @@ find_special_section_data() {
e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
o == 1 {printf("export ORC_STRUCT_SIZE=%d\n", $4); o = 2}
j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
+ f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
# Bail out once we have everything
- a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && (j == 2 || skip_j) {exit}')"
+ a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && (j == 2 || skip_j) && c == 3 {exit}')"
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
--
2.18.1

View File

@ -0,0 +1,36 @@
From b841186b9f8ced6a78953c0c109138f9aef7a53a Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 12 Mar 2020 05:10:55 -0400
Subject: [PATCH 22/24] use original reloc for symbols exported from modules
symbols exported in a patch will generate a symbol version with
object module name in Module.symvers, but the symbol is actually
in patch module which cause livepatch symbol lookup failed.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index aa5c5c4..59d491d 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -3317,13 +3317,7 @@ static bool need_dynrela(struct lookup_table *table, struct section *sec, const
return false;
}
- /*
- * The symbol is exported by the to-be-patched module, or by
- * another module which the patched module depends on. Use a
- * dynrela because of late module loading: the patch module may
- * be loaded before the to-be-patched (or other) module.
- */
- return true;
+ return false;
}
if (symbol.global) {
--
2.23.0

View File

@ -0,0 +1,47 @@
From 7fa14b0c6f2e42cdf76b44b1337eb27e5b777d14 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:38 +0000
Subject: [PATCH 23/24] 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 <xiezhipeng1@huawei.com>
Tested-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Li Bin <huawei.libin@huawei.com>
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 59d491d..3a12ee1 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -3238,6 +3238,12 @@ static bool need_dynrela(struct lookup_table *table, struct section *sec, const
return false;
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)
+ return true;
/*
* Internal symbols usually don't need dynrelas, because they
* live in the patch module and can be relocated normally.
--
2.23.0

View File

@ -1,65 +0,0 @@
From 459018cfabc65e9f29bf25476c727b4d5d8089c4 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 22 Apr 2020 05:55:33 -0400
Subject: [PATCH 23/23] create-diff-object: fix duplicate symbols for vmlinux
symbol pos in vmlinux may be different with runtime
/proc/kallsyms, use ref_name and ref_offset method too.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 36 ++++++++++++++++---------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 4fa4488..ad5746b 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -3110,25 +3110,27 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
else {
/* for modules, src is discovered at runtime */
ksyms[index].src = 0;
- if (lookup_is_duplicate_symbol(table, rela->sym->name, objname,
- result.pos)) {
- struct lookup_refsym refsym;
-
- if (lookup_ref_symbol_offset(table, rela->sym->name,
- &refsym, objname, &ref_offset))
- ERROR("unresolvable ambiguity on symbol %s\n",
- rela->sym->name);
-
- /* add rela to fill in ref_name field */
- ALLOC_LINK(rela2, &krela_sec->rela->relas);
- rela2->sym = strsym;
- rela2->type = absolute_rela_type;
- rela2->addend = offset_of_string(&kelf->strings,
- refsym.name);
- rela2->offset = (unsigned int)(index * sizeof(*krelas) +
+ }
+
+ if (lookup_is_duplicate_symbol(table, rela->sym->name, objname,
+ result.pos)) {
+ struct lookup_refsym refsym;
+
+ if (lookup_ref_symbol_offset(table, rela->sym->name,
+ &refsym, objname, &ref_offset))
+ ERROR("unresolvable ambiguity on symbol %s\n",
+ rela->sym->name);
+
+ /* add rela to fill in ref_name field */
+ ALLOC_LINK(rela2, &krela_sec->rela->relas);
+ rela2->sym = strsym;
+ rela2->type = absolute_rela_type;
+ rela2->addend = offset_of_string(&kelf->strings,
+ refsym.name);
+ rela2->offset = (unsigned int)(index * sizeof(*krelas) +
offsetof(struct kpatch_relocation, ref_name));
- }
}
+
ksyms[index].pos = result.pos;
ksyms[index].type = rela->sym->type;
ksyms[index].bind = rela->sym->bind;
--
2.18.1

View File

@ -0,0 +1,29 @@
From ea05261d87f22ecebcc5e4abac662960e732e33b Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Tue, 16 Nov 2021 20:21:31 +0800
Subject: [PATCH 24/24] kpatch-build: support CROSS_COMPILE
some Makefile use $(CROSS_COMPILE)gcc to compile .o
file, append CROSS_COMPILE to MAKEVARS to make it
run into kpatch-cc.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 1 +
1 file changed, 1 insertion(+)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 2ead6e4..6a9e818 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -1016,6 +1016,7 @@ if [ "$CONFIG_CC_IS_CLANG" -eq 1 ]; then
MAKEVARS+=("HOSTCC=clang")
else
MAKEVARS+=("CC=${KPATCH_CC_PREFIX}gcc")
+ MAKEVARS+=("CROSS_COMPILE=${KPATCH_CC_PREFIX}")
fi
if [ "$CONFIG_LD_IS_LLD" -eq 1 ]; then
--
2.23.0

View File

@ -1,44 +0,0 @@
From aef88b0908ee9d36131c63493c02359a04d1304c Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 13 Nov 2020 03:05:22 -0500
Subject: [PATCH] optimize for out of tree module
some out-of-tree modules's Module.symvers not in SRCDIR
some out-of-tree modules's obj has relative path like /xxx/./xxx.o
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 1 +
kpatch-build/kpatch-gcc | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 523d5df..6238bc8 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -1035,6 +1035,7 @@ for i in $FILES; do
BUILDDIR="/lib/modules/$ARCHVERSION/build/"
SYMVERS_FILE="$TEMPDIR/Module.symvers"
[[ -e $SRCDIR/Module.symvers ]] && cp "$SRCDIR/Module.symvers" "$SYMVERS_FILE"
+ [[ -e $USERMODBUILDDIR/Module.symvers ]] && cp "$USERMODBUILDDIR/Module.symvers" $SYMVERS_FILE
awk '{ print $1 "\t" $2 "\t" $3 "\t" $4}' "${BUILDDIR}/Module.symvers" >> "$SYMVERS_FILE"
fi
fi
diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc
index 6ad6ebc..2b2490e 100755
--- a/kpatch-build/kpatch-gcc
+++ b/kpatch-build/kpatch-gcc
@@ -25,7 +25,9 @@ if [[ "$TOOLCHAINCMD" =~ "${ARCH_COMPILE}gcc" ||
[[ "$obj" = */.tmp_*.o ]] && obj="${obj/.tmp_/}"
relobj=${obj//$KPATCH_GCC_SRCDIR\//}
- case "$relobj" in
+ tmpobj=$(readlink -f $obj)
+ relobj2=${tmpobj//$KPATCH_GCC_SRCDIR\//}
+ case "$relobj2" in
*.mod.o|\
*built-in.o|\
*built-in.a|\
--
2.18.1

View File

@ -1,42 +0,0 @@
From 55a2778284c088f4c383cf364bef18f1b5b88531 Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
Date: Thu, 4 Mar 2021 12:47:43 +0100
Subject: [PATCH] create-build-diff: support for .cold functions with no id
suffix
create-build-diff expects .cold functions to be suffixed by an id, which
is not always the case. Drop the trailing '.' when searching for cold
functions.
Fixes: #1160
Signed-off-by: Artem Savkov <asavkov@redhat.com>
---
kpatch-build/create-diff-object.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 6b19e1e..d20f2f1 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -124,7 +124,7 @@ static int is_bundleable(struct symbol *sym)
if (sym->type == STT_FUNC &&
!strncmp(sym->sec->name, ".text.unlikely.",15) &&
(!strcmp(sym->sec->name + 15, sym->name) ||
- (strstr(sym->name, ".cold.") &&
+ (strstr(sym->name, ".cold") &&
!strncmp(sym->sec->name + 15, sym->name, strlen(sym->sec->name) - 15))))
return 1;
@@ -248,7 +248,7 @@ static void kpatch_detect_child_functions(struct kpatch_elf *kelf)
list_for_each_entry(sym, &kelf->symbols, list) {
char *coldstr;
- coldstr = strstr(sym->name, ".cold.");
+ coldstr = strstr(sym->name, ".cold");
if (coldstr != NULL) {
char *pname;
--
2.27.0

View File

@ -1,62 +0,0 @@
From b381a0cc0b900d042ff6a718ef9795101310d702 Mon Sep 17 00:00:00 2001
From: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
Date: Wed, 17 Jun 2020 19:51:56 +0530
Subject: [PATCH] lookup: Add __UNIQUE_ID_ to maybe_discarded_sym list
Linux kernel tristate config options allows selected feature, either to
be built-in to the kernel or to be built as a kernel module. When built
as a kernel module, it's expected that the module, will be built with
module information such as author, license, description and others.
For each of the modinfo, a corresponding __UNIQUE_ID_ symbol is
generated. Their lookup succeeds in the case of module but fails when
selected to built-in to the kernel, the reason being that the kernel
discards these __UNIQUE_ID_ symbols during linking. Add __UNIQUE_ID_
symbols to maybe_discarded_sym list, to avoid failure in case of
table->object is vmlinux.
i.e.:
# cat .config|grep IOSCHED_BFQ (can be compiled as module too)
CONFIG_IOSCHED_BFQ=y
# readelf -sW ./block/bfq-iosched.o|grep UNIQUE
219: 0000000000000000 54 OBJECT LOCAL DEFAULT 267 __UNIQUE_ID_description223
220: 0000000000000036 16 OBJECT LOCAL DEFAULT 267 __UNIQUE_ID_license222
221: 0000000000000046 19 OBJECT LOCAL DEFAULT 267 __UNIQUE_ID_file221
222: 0000000000000059 25 OBJECT LOCAL DEFAULT 267 __UNIQUE_ID_author220
223: 0000000000000072 22 OBJECT LOCAL DEFAULT 267 __UNIQUE_ID_alias219
the line below before the kpatch error, is a debug printf to find the failing lookup symbol:
Failed lookup for __UNIQUE_ID_description223
/root/kpatch/kpatch-build/create-diff-object: ERROR: bfq-iosched.o: find_local_syms: 180: couldn't find matching bfq-iosched.c local symbols in ./vmlinux symbol table
with the patch, it successfully builds with both y/m config options:
...
bfq-iosched.o: changed function: bfq_idle_slice_timer
Patched objects: vmlinux
Building patch module:
livepatch-0001-block-bfq-fix-use-after-free-in-b.ko
SUCCESS
Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com>
---
kpatch-build/lookup.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index 4f8c779..9086c9c 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -83,7 +83,8 @@ static int maybe_discarded_sym(const char *name)
if (!strncmp(name, "__exitcall_", 11) ||
!strncmp(name, "__brk_reservation_fn_", 21) ||
!strncmp(name, "__func_stack_frame_non_standard_", 32) ||
- !strncmp(name, "__addressable_", 14))
+ !strncmp(name, "__addressable_", 14) ||
+ !strncmp(name, "__UNIQUE_ID_", 12))
return 1;
return 0;
--
2.27.0

View File

@ -1,51 +0,0 @@
From 6acafe200135f0299f4834ba7dcea5d582d75a0a Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Sat, 21 Aug 2021 04:07:33 -0400
Subject: [PATCH] create-diff-object: error on detect new/changed
ALTINSTR_ENTRY_CB
ALTINSTR_ENTRY_CB have callback which reference to other function
in .altinstructions, currently kpatch don't support new/changed
ALTINSTR_ENTRY_CB, so error on detect this case.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index d20f2f1..07a1815 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2227,6 +2227,8 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf,
* aren't sorted (e.g. .rela.fixup), so go through the entire
* rela list each time.
*/
+ int i = 0;
+ struct rela *lastrela = NULL;
list_for_each_entry_safe(rela, safe, &sec->relas, list) {
if (rela->offset >= src_offset &&
rela->offset < src_offset + group_size) {
@@ -2239,12 +2241,19 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf,
rela->sym->include = 1;
+ if (!strcmp(special->name, ".altinstructions")) {
+ if (i % 2 == 1 && strcmp(rela->sym->name , ".altinstr_replacement")) {
+ DIFF_FATAL("%s have entry in .altinstructions which have callback %s instead of new instruction", lastrela->sym->name, rela->sym->name);
+ }
+ }
if (!strcmp(special->name, ".fixup"))
kpatch_update_ex_table_addend(kelf, special,
src_offset,
dest_offset,
group_size);
+ lastrela = rela;
+ i++;
}
}
--
2.27.0

View File

@ -1,104 +0,0 @@
From 8f5c1ff32fcc519bf061f68a481116f622b9cef8 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 10 Sep 2021 04:34:40 -0400
Subject: [PATCH] kpatch: update sympos for duplicate symbols in vmlinux
kallsyms in vmlinux is sorted by address, so symbol order
in vmlinux is different from /proc/kallsyms, update sympos
when patching duplicate symbol function.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
Signed-off-by: hubin57 <hubin57@huawei.com>
---
kpatch-build/create-diff-object.c | 26 ++++++--------------------
kpatch-build/lookup.c | 24 ++++++++++++++++++++++++
kpatch-build/lookup.h | 2 ++
3 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index afd5e3b..ff2b0e4 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2813,26 +2813,12 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
funcs[index].new_size = sym->sym.st_size;
funcs[index].sympos = result.pos;
if (lookup_is_duplicate_symbol(table, sym->name, objname, result.pos)) {
- struct lookup_refsym refsym;
- long offset;
-
- if (lookup_ref_symbol_offset(table, sym->name, &refsym,
- objname, &offset))
- ERROR("unresolvable ambiguity on symbol %s\n", sym->name);
-
- funcs[index].ref_offset = offset;
-
- /*
- * Add a relocation that will populate
- * the funcs[index].ref_name field.
- */
- ALLOC_LINK(rela, &relasec->relas);
- rela->sym = strsym;
- rela->type = absolute_rela_type;
- rela->addend = offset_of_string(&kelf->strings, refsym.name);
- rela->offset = (unsigned int)(index * sizeof(*funcs) +
- offsetof(struct kpatch_patch_func, ref_name));
-
+ if (!strcmp(objname, "vmlinux")) {
+ result.pos = get_vmlinux_duplicate_symbol_pos(table, sym->name, result.value);
+ log_debug("update %s sympos from %ld to %ld\n",
+ sym->name, funcs[index].sympos, result.pos);
+ funcs[index].sympos = result.pos;
+ }
}
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index 888bcc9..aa8527d 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -526,6 +526,30 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
return 1;
}
+/*
+ * In case sometimes the sympos of duplicate symbols are different in vmlinux and
+ * /proc/kallsyms, and causes lookup_local_symbol to save wrong sympos in result,
+ * this function returns correct sympos of the symbol, by comparing
+ * address value with the symbol in vmlinux symbol table.
+ */
+unsigned long get_vmlinux_duplicate_symbol_pos(struct lookup_table *table,
+ char *name, unsigned long value)
+{
+ struct object_symbol *sym;
+ unsigned long pos = 1;
+ int i;
+
+ for_each_obj_symbol(i, sym, table) {
+ if (strcmp(sym->name, name))
+ continue;
+
+ if (sym->value < value)
+ pos++;
+ }
+
+ return pos;
+}
+
int lookup_is_exported_symbol(struct lookup_table *table, char *name)
{
struct export_symbol *sym, *match = NULL;
diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h
index daeea73..c745366 100644
--- a/kpatch-build/lookup.h
+++ b/kpatch-build/lookup.h
@@ -37,5 +37,7 @@ int lookup_is_duplicate_symbol(struct lookup_table *table, char *name,
int lookup_ref_symbol_offset(struct lookup_table *table, char *name,
struct lookup_refsym *refsym, char *objname,
long *offset);
+unsigned long get_vmlinux_duplicate_symbol_pos(struct lookup_table *table, char *name,
+ unsigned long value);
#endif /* _LOOKUP_H_ */
--
2.27.0

View File

@ -1,36 +0,0 @@
From fa5a95cafdb034b825242a93ef1b4ce57985a93d Mon Sep 17 00:00:00 2001
From: Josh Poimboeuf <jpoimboe@redhat.com>
Date: Tue, 13 Apr 2021 13:58:59 -0500
Subject: [PATCH] create-diff-object: Fix out-of-range relocation error message
Showing sec+addend isn't valid, show sym+addend instead.
Before:
create-diff-object: ERROR: sys.o: kpatch_check_relocations: 2550: out-of-range relocation .rodata.__kpatch_do_sys_uname.str1.1+139 in .rela.text.__kpatch_do_sys_uname
After:
create-diff-object: ERROR: sys.o: kpatch_check_relocations: 2550: out-of-range relocation .LC7+139 in .rela.text.__kpatch_do_sys_uname
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
kpatch-build/create-diff-object.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 82e486f..d427beb 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2547,7 +2547,7 @@ static void kpatch_check_relocations(struct kpatch_elf *kelf)
if (rela->sym->sec) {
sdata = rela->sym->sec->data;
if (rela->addend > (long)sdata->d_size) {
- ERROR("out-of-range relocation %s+%lx in %s", rela->sym->sec->name,
+ ERROR("out-of-range relocation %s+%lx in %s", rela->sym->name,
rela->addend, sec->name);
}
}
--
2.23.0

View File

@ -1,32 +0,0 @@
From 81f9ca4833bf9c5867858d633c340cedca554ca6 Mon Sep 17 00:00:00 2001
From: Josh Poimboeuf <jpoimboe@redhat.com>
Date: Tue, 13 Apr 2021 14:00:41 -0500
Subject: [PATCH] create-diff-object: Fix out-of-range relocation check
Improve the relocation check for the case where the referenced symbol
isn't at the beginning of the section.
Note that the check still isn't perfect, as many relocations have a
negative addend. But it's still a lot better than nothing.
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
kpatch-build/create-diff-object.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index d427beb..14eb1f5 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2546,7 +2546,7 @@ static void kpatch_check_relocations(struct kpatch_elf *kelf)
list_for_each_entry(rela, &sec->relas, list) {
if (rela->sym->sec) {
sdata = rela->sym->sec->data;
- if (rela->addend > (long)sdata->d_size) {
+ if ((long)rela->sym->sym.st_value + rela->addend > (long)sdata->d_size) {
ERROR("out-of-range relocation %s+%lx in %s", rela->sym->name,
rela->addend, sec->name);
}
--
2.23.0

View File

@ -1,25 +0,0 @@
From eaaced1912c43103749366927daff5794ea4f404 Mon Sep 17 00:00:00 2001
From: gouhao <gouhao@uniontech.com>
Date: Wed, 8 Sep 2021 09:37:08 +0800
Subject: [PATCH] add openEuler build support
---
kpatch-build/kpatch-build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 495ca3d..49c0045 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -696,7 +696,7 @@ fi
# shellcheck disable=SC1090
[[ -f "$RELEASE_FILE" ]] && source "$RELEASE_FILE"
DISTRO="$ID"
-if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]]; then
+if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]] || [[ "$DISTRO" = openEuler ]]; then
[[ -z "$VMLINUX" ]] && VMLINUX="/usr/lib/debug/lib/modules/$ARCHVERSION/vmlinux"
[[ -e "$VMLINUX" ]] || die "kernel-debuginfo-$ARCHVERSION not installed"
--
2.23.0

View File

@ -1,232 +0,0 @@
From 005bd5ac6878b48ade7402156b2224c1b8c8ff5e Mon Sep 17 00:00:00 2001
From: Joe Lawrence <joe.lawrence@redhat.com>
Date: Fri, 24 Jul 2020 15:33:28 -0400
Subject: [PATCH] livepatch-patch-hook: add comments
Add some commentary to the livepatch-patch-hook file to explain what
it's doing.
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
---
kmod/patch/livepatch-patch-hook.c | 106 ++++++++++++++++++++++++++++++
1 file changed, 106 insertions(+)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index d3fb1db..17b40b9 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -92,10 +92,28 @@
* done, the scaffold structs are no longer needed.
*/
+/*
+ * lpatch is the kernel data structure that will be created on patch
+ * init, registered with the livepatch API on init, and finally
+ * unregistered when the patch exits. Its struct klp_object *objs
+ * member must be dynamically allocated according to the number of
+ * target objects it will be patching.
+ */
static struct klp_patch *lpatch;
static LIST_HEAD(patch_objects);
static int patch_objects_nr;
+
+/**
+ * struct patch_object - scaffolding structure tracking patch target objects
+ * @list: list of patch_object (threaded onto patch_objects)
+ * @funcs: list of patch_func associated with this object
+ * @relocs: list of patch_reloc associated with this object
+ * @callbacks: kernel struct of object callbacks
+ * @name: patch target object name (NULL for vmlinux)
+ * @funcs_nr: count of kpatch_patch_func added to @funcs
+ * @relocs_nr: count of patch_reloc added to @relocs
+ */
struct patch_object {
struct list_head list;
struct list_head funcs;
@@ -107,16 +125,36 @@ struct patch_object {
int funcs_nr, relocs_nr;
};
+/**
+ * struct patch_func - scaffolding structure for kpatch_patch_func
+ * @list: list of patch_func (threaded onto patch_object.funcs)
+ * @kfunc: array of kpatch_patch_func
+ */
struct patch_func {
struct list_head list;
struct kpatch_patch_func *kfunc;
};
+/**
+ * struct patch_reloc - scaffolding structure for kpatch_patch_dynrela
+ * @list: list of patch_reloc (threaded onto patch_object.relocs)
+ * @kdynrela: array of kpatch_patch_dynrela
+ */
struct patch_reloc {
struct list_head list;
struct kpatch_patch_dynrela *kdynrela;
};
+/**
+ * patch_alloc_new_object() - creates and initializes a new patch_object
+ * @name: target object name
+ *
+ * Return: pointer to new patch_object, NULL on failure.
+ *
+ * Does not check for previously created patch_objects with the same
+ * name. Updates patch_objects_nr and threads new data structure onto
+ * the patch_objects list.
+ */
static struct patch_object *patch_alloc_new_object(const char *name)
{
struct patch_object *object;
@@ -135,6 +173,16 @@ static struct patch_object *patch_alloc_new_object(const char *name)
return object;
}
+/**
+ * patch_find_object_by_name() - find or create a patch_object with a
+ * given name
+ * @name: target object name
+ *
+ * Return: pointer to patch_object, NULL on failure.
+ *
+ * Searches the patch_objects list for an already created instance with
+ * @name, otherwise tries to create it via patch_alloc_new_object()
+ */
static struct patch_object *patch_find_object_by_name(const char *name)
{
struct patch_object *object;
@@ -146,6 +194,17 @@ static struct patch_object *patch_find_object_by_name(const char *name)
return patch_alloc_new_object(name);
}
+/**
+ * patch_add_func_to_object() - create scaffolding from kpatch_patch_func data
+ *
+ * @kfunc: Individual kpatch_patch_func pointer
+ *
+ * Return: 0 on success, -ENOMEM on failure.
+ *
+ * Builds scaffolding data structures from .kpatch.funcs section's array
+ * of kpatch_patch_func structures. Updates the associated
+ * patch_object's funcs_nr count.
+ */
static int patch_add_func_to_object(struct kpatch_patch_func *kfunc)
{
struct patch_func *func;
@@ -168,6 +227,17 @@ static int patch_add_func_to_object(struct kpatch_patch_func *kfunc)
}
#ifndef HAVE_ELF_RELOCS
+/**
+ * patch_add_reloc_to_object() - create scaffolding from kpatch_patch_dynrela data
+ *
+ * @kdynrela: Individual kpatch_patch_dynrela pointer
+ *
+ * Return: 0 on success, -ENOMEM on failure.
+ *
+ * Builds scaffolding data structures from .kpatch.dynrelas section's array
+ * of kpatch_patch_dynrela structures. Updates the associated
+ * patch_object's relocs_nr count.
+ */
static int patch_add_reloc_to_object(struct kpatch_patch_dynrela *kdynrela)
{
struct patch_reloc *reloc;
@@ -190,6 +260,9 @@ static int patch_add_reloc_to_object(struct kpatch_patch_dynrela *kdynrela)
}
#endif
+/**
+ * patch_free_scaffold() - tear down the temporary kpatch scaffolding
+ */
static void patch_free_scaffold(void) {
struct patch_func *func, *safefunc;
struct patch_object *object, *safeobject;
@@ -215,6 +288,9 @@ static void patch_free_scaffold(void) {
}
}
+/**
+ * patch_free_livepatch() - release the klp_patch and friends
+ */
static void patch_free_livepatch(struct klp_patch *patch)
{
struct klp_object *object;
@@ -234,6 +310,7 @@ static void patch_free_livepatch(struct klp_patch *patch)
}
}
+/* Defined by kpatch.lds.S */
extern struct kpatch_pre_patch_callback __kpatch_callbacks_pre_patch[], __kpatch_callbacks_pre_patch_end[];
extern struct kpatch_post_patch_callback __kpatch_callbacks_post_patch[], __kpatch_callbacks_post_patch_end[];
extern struct kpatch_pre_unpatch_callback __kpatch_callbacks_pre_unpatch[], __kpatch_callbacks_pre_unpatch_end[];
@@ -267,6 +344,14 @@ static int add_kpatch_objects(void)
#ifdef HAVE_CALLBACKS
+/**
+ * add_callbacks_to_patch_objects() - create patch_objects that have callbacks
+ *
+ * Return: 0 on success, -ENOMEM or -EINVAL on failure
+ *
+ * Iterates through all kpatch pre/post-(un)patch callback data
+ * structures and creates scaffolding patch_objects for them.
+ */
static int add_callbacks_to_patch_objects(void)
{
struct kpatch_pre_patch_callback *p_pre_patch_callback;
@@ -356,6 +441,7 @@ static inline int add_callbacks_to_patch_objects(void)
}
#endif /* HAVE_CALLBACKS */
+/* Defined by kpatch.lds.S */
extern struct kpatch_patch_func __kpatch_funcs[], __kpatch_funcs_end[];
#ifndef HAVE_ELF_RELOCS
extern struct kpatch_patch_dynrela __kpatch_dynrelas[], __kpatch_dynrelas_end[];
@@ -375,6 +461,12 @@ static int __init patch_init(void)
struct klp_reloc *lrelocs, *lreloc;
#endif
+
+ /*
+ * Step 1 - read from output.o, create temporary scaffolding
+ * data-structures
+ */
+
/* organize functions and relocs by object in scaffold */
for (kfunc = __kpatch_funcs;
kfunc != __kpatch_funcs_end;
@@ -404,6 +496,16 @@ static int __init patch_init(void)
/* past this point, only possible return code is -ENOMEM */
ret = -ENOMEM;
+ /*
+ * Step 2 - create livepatch klp_patch and friends
+ *
+ * There are two dynamically allocated parts:
+ *
+ * klp_patch
+ * klp_object objs [patch_objects_nr] <= i
+ * klp_func funcs [object->funcs_nr] <= j
+ */
+
/* allocate and fill livepatch structures */
lpatch = kzalloc(sizeof(*lpatch), GFP_KERNEL);
if (!lpatch)
@@ -478,6 +580,10 @@ static int __init patch_init(void)
i++;
}
+ /*
+ * Step 3 - throw away scaffolding
+ */
+
/*
* Once the patch structure that the live patching API expects
* has been built, we can release the scaffold structure.
--
2.27.0

Binary file not shown.

BIN
kpatch-0.9.5.tar.gz Normal file

Binary file not shown.

View File

@ -1,7 +1,7 @@
Name: kpatch Name: kpatch
Epoch: 1 Epoch: 1
Version: 0.9.1 Version: 0.9.5
Release: 21 Release: 1
Summary: A Linux dynamic kernel patching infrastructure Summary: A Linux dynamic kernel patching infrastructure
License: GPLv2 License: GPLv2
@ -12,41 +12,31 @@ Source1: os_hotpatch
Source2: livepatch Source2: livepatch
Source3: make_hotpatch Source3: make_hotpatch
Patch0001:0001-support-compile-kpatch-on-aarch64.patch #custom patch
Patch0002:0002-kpatch-build-support-build-patch-for-aarch64.patch Patch0001:0001-kpatch-add-aarch64-support.patch
Patch0003:0003-create-diff-object-new-static-var-should-be-included.patch Patch0002:0002-create-diff-object-fix-symbol-changed-sections-error.patch
Patch0004:0004-livepatch-fix-use-THIS-modname-as-the-name-of-ddebug.patch Patch0003:0003-create-diff-object-support-kpatch_line_macro_change_.patch
Patch0005:0005-create-diff-object-fix-correlate-static-local-variab.patch Patch0004:0004-create-diff-object-support-skip-check-func-profiling.patch
Patch0006:0006-create-diff-object-don-t-create-dynamic-reloc-for-sy.patch Patch0005:0005-create-diff-object-new-static-var-should-be-included.patch
Patch0007:0007-create-diff-object-create-dynamic-relocs-for-changed.patch Patch0006:0006-create-diff-object-fix-correlate-static-local-variab.patch
Patch0008:0008-fix-rodata.str-problem.patch Patch0007:0007-fix-rodata.str-problem.patch
Patch0009:0009-livepatch-patch-hook-don-t-active-patch-when-insmod.patch Patch0008:0008-livepatch-patch-hook-support-no-active-after-load.patch
Patch0010:0010-kpatch-build-enhance-for-out-of-tree-module.patch Patch0009:0009-kpatch-build-enhance-for-out-of-tree-module.patch
Patch0011:0011-support-c-plus-kernel-module.patch Patch0010:0010-support-c-kernel-module.patch
Patch0012:0012-symbol-lookup-enhancement.patch Patch0011:0011-symbol-lookup-enhancement.patch
Patch0013:0013-Add-running-kernel-symbol-table-to-help-symbol-looku.patch Patch0012:0012-Add-running-kernel-symbol-table-to-help-symbol-looku.patch
Patch0014:0014-livepatch-patch-hook-support-force-enable-disable.patch Patch0013:0013-livepatch-patch-hook-support-force-enable-disable.patch
Patch0015:0015-kpatch-build-ignore-debuginfo-in-patch.patch Patch0014:0014-kpatch-build-ignore-debuginfo-in-patch.patch
Patch0016:0016-add-object-in-kpatch.patch Patch0015:0015-add-object-in-kpatch.patch
Patch0017:0017-create-diff-object-fix-.orc_unwind_ip-error.patch Patch0016:0016-create-diff-object-fix-.orc_unwind_ip-error.patch
Patch0018:0018-use-original-reloc-for-symbols-from-modules.patch Patch0017:0017-create-diff-object-add-jump-label-support.patch
Patch0019:0019-create-diff-object-add-jump-label-support.patch Patch0018:0018-kpatch-build-add-compile-flag-fno-reorder-functions.patch
Patch0020:0020-kpatch-build-add-compile-flag-fno-reorder-functions.patch Patch0019:0019-Fix-relocation-not-resolved-when-new-functions-expor.patch
Patch0021:0021-kpatch-build-don-t-copy-.config-for-out-of-tree-modu.patch Patch0020:0020-support-remove-static-variables-using-KPATCH_IGNORE_.patch
Patch0022:0022-support-force-enable-disable-for-x86.patch Patch0021:0021-create-diff-object-fix-segment-fault-when-sec2-rela-.patch
Patch0023:0023-create-diff-object-fix-duplicate-symbols-for-vmlinux.patch Patch0022:0022-use-original-reloc-for-symbols-exported-from-modules.patch
Patch0024:0024-optimize-for-out-of-tree-module.patch Patch0023:0023-create-diff-object-create-dynamic-relocs-for-changed.patch
Patch0025:0025-Fix-relocation-not-resolved-when-new-functions-expor.patch Patch0024:0024-kpatch-build-support-CROSS_COMPILE.patch
Patch0026:0026-support-remove-static-variables-using-KPATCH_IGNORE_.patch
Patch0027:0027-create-build-diff-support-for-.cold-functions-with-n.patch
Patch0028:0028-lookup-Add-__UNIQUE_ID_-to-maybe_discarded_sym-list.patch
Patch0029:0029-create-diff-object-error-on-detect-new-changed-ALTIN.patch
Patch0030:0030-kpatch-update-sympos-for-duplicate-symbols-in-vmlinu.patch
Patch0031:0031-create-diff-object-fix-segment-fault-when-sec2-rela-.patch
Patch0032:0032-create-diff-object-Fix-out-of-range-relocation-error.patch
Patch0033:0033-create-diff-object-Fix-out-of-range-relocation-check.patch
Patch0034:0034-add-openEuler-build-support.patch
Patch0035:0035-livepatch-patch-hook-add-comments.patch
BuildRequires: gcc elfutils-libelf-devel kernel-devel git BuildRequires: gcc elfutils-libelf-devel kernel-devel git
Requires: bc make gcc patch bison flex openssl-devel Requires: bc make gcc patch bison flex openssl-devel
@ -107,6 +97,12 @@ popd
%{_mandir}/man1/*.1.gz %{_mandir}/man1/*.1.gz
%changelog %changelog
* Sat Nov 13 2021 Zhipeng Xie<xiezhipeng1@huawei.com> -1:0.9.5-1
- Type:enhancement
- ID:NA
- SUG:NA
- DESC:upgrade to upstream v0.9.5
* Sat Oct 30 2021 Bin Hu<hubin57@huawei.com> -1:0.9.1-21 * Sat Oct 30 2021 Bin Hu<hubin57@huawei.com> -1:0.9.1-21
- Type:enhancement - Type:enhancement
- ID:NA - ID:NA

View File

@ -534,7 +534,7 @@ function fn_makepatch()
G_PATCH_SRC=`readlink -f $G_KERNEL_SRC` G_PATCH_SRC=`readlink -f $G_KERNEL_SRC`
if [ -d "$G_MODULE_SRC" ];then if [ -d "$G_MODULE_SRC" ];then
echo "make out of tree module hotpath" echo "make out of tree module hotpatch"
G_PATCH_SRC=$G_MODULE_SRC G_PATCH_SRC=$G_MODULE_SRC
#fn_init_module_build $G_MODULE_SRC $G_MODULE_MAKEFILE #fn_init_module_build $G_MODULE_SRC $G_MODULE_MAKEFILE
#if [ $? -ne 0 ];then #if [ $? -ne 0 ];then
@ -592,6 +592,7 @@ function fn_makepatch()
export USERMODFLAGS=`cat $G_KPATCH_FLAGS` export USERMODFLAGS=`cat $G_KPATCH_FLAGS`
export NO_PROFILING_CALLS="yes" export NO_PROFILING_CALLS="yes"
export DISABLE_AFTER_LOAD="yes" export DISABLE_AFTER_LOAD="yes"
export KEEP_JUMP_LABEL="yes"
UNAME_R=$(uname -r) UNAME_R=$(uname -r)
UNAME_R_ARCH=${UNAME_R##*.} UNAME_R_ARCH=${UNAME_R##*.}
SKIP_GCC_CHECK="" SKIP_GCC_CHECK=""
@ -599,7 +600,7 @@ function fn_makepatch()
echo "build in cross compile environment, skip gcc check" echo "build in cross compile environment, skip gcc check"
SKIP_GCC_CHECK="--skip-gcc-check" SKIP_GCC_CHECK="--skip-gcc-check"
fi fi
kpatch-build -s $G_PATCH_SRC -c $G_KERNEL_CONFIG -v $G_VMLINUX ${SKIP_GCC_CHECK} -n "${G_PREFIX}_${G_HOTPATCH_ID}" $G_DEBUG_INFO $G_PATCHFILE kpatch-build -s $G_PATCH_SRC -c $G_KERNEL_CONFIG -v $G_VMLINUX ${SKIP_GCC_CHECK} -n "${G_PREFIX}_${G_HOTPATCH_ID}" $G_DEBUG_INFO $G_PATCHFILE -R
l_ret=$? l_ret=$?
cd - &>/dev/null cd - &>/dev/null
if [ $l_ret -eq 0 ] && [ -f "$G_TMP_DIR/$G_HOTPATCH" ];then if [ $l_ret -eq 0 ] && [ -f "$G_TMP_DIR/$G_HOTPATCH" ];then