194 lines
6.6 KiB
Diff
194 lines
6.6 KiB
Diff
|
|
From 20de56a8393e6be3b556156124aa4b2139b10733 Mon Sep 17 00:00:00 2001
|
|||
|
|
From: Zhipeng Xie <xiezhipeng1@huawei.com>
|
|||
|
|
Date: Wed, 26 Feb 2020 07:36:59 -0500
|
|||
|
|
Subject: [PATCH 11/17] support c plus kernel module
|
|||
|
|
|
|||
|
|
support GNU_UNIQUE type symbols.
|
|||
|
|
support .group section corelation.
|
|||
|
|
ignore compile warning for third party modules.
|
|||
|
|
|
|||
|
|
Signed-off-by: Zhipeng Xie <root@localhost.localdomain>
|
|||
|
|
---
|
|||
|
|
kpatch-build/create-diff-object.c | 62 ++++++++++++++++++++-----------
|
|||
|
|
kpatch-build/kpatch-build | 2 +-
|
|||
|
|
kpatch-build/kpatch-elf.c | 8 +++-
|
|||
|
|
kpatch-build/kpatch-gcc | 3 +-
|
|||
|
|
kpatch-build/lookup.c | 5 ++-
|
|||
|
|
5 files changed, 55 insertions(+), 25 deletions(-)
|
|||
|
|
|
|||
|
|
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
|
|||
|
|
index 643ae3e..190753a 100644
|
|||
|
|
--- a/kpatch-build/create-diff-object.c
|
|||
|
|
+++ b/kpatch-build/create-diff-object.c
|
|||
|
|
@@ -454,7 +454,7 @@ static void kpatch_compare_correlated_nonrela_section(struct section *sec)
|
|||
|
|
{
|
|||
|
|
struct section *sec1 = sec, *sec2 = sec->twin;
|
|||
|
|
|
|||
|
|
- if (sec1->sh.sh_type != SHT_NOBITS &&
|
|||
|
|
+ if (sec1->sh.sh_type != SHT_NOBITS && sec1->sh.sh_type != SHT_GROUP &&
|
|||
|
|
memcmp(sec1->data->d_buf, sec2->data->d_buf, sec1->data->d_size))
|
|||
|
|
sec->status = CHANGED;
|
|||
|
|
else
|
|||
|
|
@@ -470,7 +470,7 @@ static void kpatch_compare_correlated_section(struct section *sec)
|
|||
|
|
sec1->sh.sh_flags != sec2->sh.sh_flags ||
|
|||
|
|
sec1->sh.sh_entsize != sec2->sh.sh_entsize ||
|
|||
|
|
(sec1->sh.sh_addralign != sec2->sh.sh_addralign &&
|
|||
|
|
- !is_text_section(sec1)))
|
|||
|
|
+ !is_text_section(sec1) && strcmp(sec1->name, ".rodata")))
|
|||
|
|
DIFF_FATAL("%s section header details differ from %s", sec1->name, sec2->name);
|
|||
|
|
|
|||
|
|
/* Short circuit for mcount sections, we rebuild regardless */
|
|||
|
|
@@ -907,6 +907,33 @@ static void kpatch_correlate_section(struct section *sec1, struct section *sec2)
|
|||
|
|
kpatch_correlate_symbol(sec1->sym, sec2->sym);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
+static int kpatch_correlate_group_section(struct list_head *seclist1, struct list_head *seclist2, struct section *sec1, struct section *sec2)
|
|||
|
|
+{
|
|||
|
|
+ unsigned int *data1, *end1, *data2;
|
|||
|
|
+ struct section *isec1, *isec2;
|
|||
|
|
+
|
|||
|
|
+ if (sec1->data->d_size != sec2->data->d_size)
|
|||
|
|
+ return 1;
|
|||
|
|
+ data1 = sec1->data->d_buf;
|
|||
|
|
+ data2 = sec2->data->d_buf;
|
|||
|
|
+ end1 = sec1->data->d_buf + sec1->data->d_size;
|
|||
|
|
+ data1++;
|
|||
|
|
+ data2++;
|
|||
|
|
+ while (data1 < end1) {
|
|||
|
|
+ isec1 = find_section_by_index(seclist1, *data1);
|
|||
|
|
+ if (!isec1)
|
|||
|
|
+ ERROR("group section not found");
|
|||
|
|
+ isec2 = find_section_by_index(seclist2, *data2);
|
|||
|
|
+ if (!isec2)
|
|||
|
|
+ ERROR("group section not found");
|
|||
|
|
+ if (strcmp(isec1->name, isec2->name))
|
|||
|
|
+ return 1;
|
|||
|
|
+ data1++;
|
|||
|
|
+ data2++;
|
|||
|
|
+ }
|
|||
|
|
+ return 0;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
static void kpatch_correlate_sections(struct list_head *seclist1, struct list_head *seclist2)
|
|||
|
|
{
|
|||
|
|
struct section *sec1, *sec2;
|
|||
|
|
@@ -924,15 +951,19 @@ static void kpatch_correlate_sections(struct list_head *seclist1, struct list_he
|
|||
|
|
sec1->secsym))
|
|||
|
|
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 (sec1->sh.sh_type == SHT_GROUP) {
|
|||
|
|
- if (sec1->data->d_size != sec2->data->d_size)
|
|||
|
|
- continue;
|
|||
|
|
- if (memcmp(sec1->data->d_buf, sec2->data->d_buf,
|
|||
|
|
- sec1->data->d_size))
|
|||
|
|
+ if(kpatch_correlate_group_section(seclist1, seclist2, sec1, sec2))
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@@ -1507,17 +1538,6 @@ static void kpatch_verify_patchability(struct kpatch_elf *kelf)
|
|||
|
|
errs++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- if (sec->status != SAME && sec->grouped) {
|
|||
|
|
- log_normal("changed section %s is part of a section group\n",
|
|||
|
|
- sec->name);
|
|||
|
|
- errs++;
|
|||
|
|
- }
|
|||
|
|
-
|
|||
|
|
- if (sec->sh.sh_type == SHT_GROUP && sec->status == NEW) {
|
|||
|
|
- log_normal("new/changed group sections are not supported\n");
|
|||
|
|
- errs++;
|
|||
|
|
- }
|
|||
|
|
-
|
|||
|
|
/*
|
|||
|
|
* ensure we aren't including .data.* or .bss.*
|
|||
|
|
* (.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
|
|||
|
|
index 4e38412..4896136 100755
|
|||
|
|
--- a/kpatch-build/kpatch-build
|
|||
|
|
+++ b/kpatch-build/kpatch-build
|
|||
|
|
@@ -1157,7 +1157,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-elf.c b/kpatch-build/kpatch-elf.c
|
|||
|
|
index 1c0e099..debf028 100644
|
|||
|
|
--- a/kpatch-build/kpatch-elf.c
|
|||
|
|
+++ b/kpatch-build/kpatch-elf.c
|
|||
|
|
@@ -708,8 +708,14 @@ void kpatch_reindex_elements(struct kpatch_elf *kelf)
|
|||
|
|
unsigned int index;
|
|||
|
|
|
|||
|
|
index = 1; /* elf write function handles NULL section 0 */
|
|||
|
|
- list_for_each_entry(sec, &kelf->sections, list)
|
|||
|
|
+ list_for_each_entry(sec, &kelf->sections, list) {
|
|||
|
|
sec->index = index++;
|
|||
|
|
+ /*
|
|||
|
|
+ * since we exclude .group section, we clear SHF_GROUP
|
|||
|
|
+ * for every section in case of link error.
|
|||
|
|
+ * */
|
|||
|
|
+ sec->sh.sh_flags &= (~SHF_GROUP);
|
|||
|
|
+ }
|
|||
|
|
|
|||
|
|
index = 0;
|
|||
|
|
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
|
|||
|
|
index 8387e8b..4e2fcb9 100644
|
|||
|
|
--- a/kpatch-build/lookup.c
|
|||
|
|
+++ b/kpatch-build/lookup.c
|
|||
|
|
@@ -255,6 +255,8 @@ static void symtab_read(struct lookup_table *table, char *path)
|
|||
|
|
table->obj_syms[i].bind = STB_GLOBAL;
|
|||
|
|
} else if (!strcmp(bind, "WEAK")) {
|
|||
|
|
table->obj_syms[i].bind = STB_WEAK;
|
|||
|
|
+ } else if (!strcmp(bind, "UNIQUE")) {
|
|||
|
|
+ table->obj_syms[i].bind = STB_GNU_UNIQUE;
|
|||
|
|
} else {
|
|||
|
|
ERROR("unknown symbol bind %s", bind);
|
|||
|
|
}
|
|||
|
|
@@ -431,7 +433,8 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
|
|||
|
|
|
|||
|
|
memset(result, 0, sizeof(*result));
|
|||
|
|
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
|
|||
|
|
+ || sym->bind == STB_GNU_UNIQUE) &&
|
|||
|
|
!strcmp(sym->name, name)) {
|
|||
|
|
result->value = sym->value;
|
|||
|
|
result->size = sym->size;
|
|||
|
|
--
|
|||
|
|
2.18.1
|
|||
|
|
|