2024-03-02 00:18:20 +08:00
|
|
|
From 44139a57987e0d47fc7e1a39ca1e4ee37eb93a87 Mon Sep 17 00:00:00 2001
|
2020-02-27 17:15:29 -05:00
|
|
|
From: Zhipeng Xie <xiezhipeng1@huawei.com>
|
|
|
|
|
Date: Wed, 26 Feb 2020 22:03:55 -0500
|
2024-03-02 00:18:20 +08:00
|
|
|
Subject: [PATCH 10/38] symbol lookup enhancement
|
2020-02-27 17:15:29 -05:00
|
|
|
|
|
|
|
|
For symbols which have same name in one module or have
|
|
|
|
|
length longger than KSYM_NAME_LEN(128 bytes). we add
|
|
|
|
|
some work around to lookup another unique symbol and add
|
|
|
|
|
relative offset to get the actual symbol. This patch
|
|
|
|
|
depend on a kernel patch to deal with new relocation
|
|
|
|
|
style.
|
|
|
|
|
|
|
|
|
|
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
|
|
|
|
|
---
|
|
|
|
|
kmod/patch/kpatch-patch.h | 4 +
|
2021-11-16 12:10:06 +08:00
|
|
|
kpatch-build/create-diff-object.c | 40 +++++++-
|
|
|
|
|
kpatch-build/create-klp-module.c | 25 ++++-
|
2020-02-27 17:15:29 -05:00
|
|
|
kpatch-build/kpatch-build | 12 +++
|
|
|
|
|
kpatch-build/kpatch-intermediate.h | 2 +
|
2021-11-16 12:10:06 +08:00
|
|
|
kpatch-build/lookup.c | 159 ++++++++++++++++++++++++++++-
|
|
|
|
|
kpatch-build/lookup.h | 15 +++
|
|
|
|
|
7 files changed, 247 insertions(+), 10 deletions(-)
|
2020-02-27 17:15:29 -05:00
|
|
|
|
|
|
|
|
diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h
|
2020-09-12 05:45:06 -04:00
|
|
|
index da4f6a0..9df7818 100644
|
2020-02-27 17:15:29 -05:00
|
|
|
--- a/kmod/patch/kpatch-patch.h
|
|
|
|
|
+++ b/kmod/patch/kpatch-patch.h
|
|
|
|
|
@@ -30,6 +30,8 @@ struct kpatch_patch_func {
|
|
|
|
|
unsigned long sympos;
|
|
|
|
|
char *name;
|
|
|
|
|
char *objname;
|
|
|
|
|
+ char *ref_name;
|
|
|
|
|
+ long ref_offset;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct kpatch_patch_dynrela {
|
|
|
|
|
@@ -41,6 +43,8 @@ struct kpatch_patch_dynrela {
|
|
|
|
|
char *objname;
|
|
|
|
|
int external;
|
2020-05-11 14:59:12 +08:00
|
|
|
long addend;
|
2020-09-12 05:45:06 -04:00
|
|
|
+ char *ref_name;
|
|
|
|
|
+ long ref_offset;
|
2020-02-27 17:15:29 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct kpatch_pre_patch_callback {
|
|
|
|
|
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
|
2024-03-02 00:18:20 +08:00
|
|
|
index d3088b1..ee06ad1 100644
|
2020-02-27 17:15:29 -05:00
|
|
|
--- a/kpatch-build/create-diff-object.c
|
|
|
|
|
+++ b/kpatch-build/create-diff-object.c
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -3231,6 +3231,14 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
|
2021-11-16 12:10:06 +08:00
|
|
|
funcs[index].old_size = symbol.size;
|
|
|
|
|
funcs[index].new_size = sym->sym.st_size;
|
|
|
|
|
funcs[index].sympos = symbol.sympos;
|
|
|
|
|
+ if (lookup_is_duplicate_symbol(table, sym->name, objname, symbol.sympos)) {
|
|
|
|
|
+ if (!strcmp(objname, "vmlinux")) {
|
|
|
|
|
+ symbol.sympos = get_vmlinux_duplicate_symbol_pos(table, sym->name, symbol.addr);
|
|
|
|
|
+ log_debug("update %s sympos from %ld to %ld\n",
|
|
|
|
|
+ sym->name, funcs[index].sympos, symbol.sympos);
|
|
|
|
|
+ funcs[index].sympos = symbol.sympos;
|
2020-02-27 17:15:29 -05:00
|
|
|
+ }
|
2021-11-16 12:10:06 +08:00
|
|
|
+ }
|
2020-02-27 17:15:29 -05:00
|
|
|
|
2021-11-16 12:10:06 +08:00
|
|
|
/*
|
|
|
|
|
* Add a relocation that will populate the
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -3249,7 +3257,8 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
|
2021-11-16 12:10:06 +08:00
|
|
|
ALLOC_LINK(rela, &relasec->relas);
|
|
|
|
|
rela->sym = strsym;
|
2023-01-30 16:10:43 +08:00
|
|
|
rela->type = absolute_rela_type(kelf);
|
2021-11-16 12:10:06 +08:00
|
|
|
- rela->addend = offset_of_string(&kelf->strings, sym->name);
|
|
|
|
|
+ rela->addend = offset_of_string(&kelf->strings,
|
2020-09-12 05:45:06 -04:00
|
|
|
+ strndup(sym->name, KSYM_NAME_LEN-1));
|
2021-11-16 12:10:06 +08:00
|
|
|
rela->offset = (unsigned int)(index * sizeof(*funcs) +
|
|
|
|
|
offsetof(struct kpatch_patch_func, name));
|
2020-02-27 17:15:29 -05:00
|
|
|
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -3490,6 +3499,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
|
2021-11-16 12:10:06 +08:00
|
|
|
bool special;
|
|
|
|
|
bool vmlinux = !strcmp(objname, "vmlinux");
|
|
|
|
|
struct special_section *s;
|
2020-02-27 17:15:29 -05:00
|
|
|
+ long ref_offset;
|
|
|
|
|
|
2021-11-16 12:10:06 +08:00
|
|
|
/* count rela entries that need to be dynamic */
|
|
|
|
|
nr = 0;
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -3590,12 +3600,34 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
|
2021-11-16 12:10:06 +08:00
|
|
|
rela->sym->name, symbol.objname,
|
|
|
|
|
symbol.sympos);
|
2020-02-27 17:15:29 -05:00
|
|
|
|
|
|
|
|
+ ref_offset = 0;
|
|
|
|
|
/* Fill in ksyms[index] */
|
|
|
|
|
if (vmlinux)
|
2021-11-16 12:10:06 +08:00
|
|
|
ksyms[index].src = symbol.addr;
|
2020-02-27 17:15:29 -05:00
|
|
|
- else
|
|
|
|
|
+ else {
|
|
|
|
|
/* for modules, src is discovered at runtime */
|
|
|
|
|
ksyms[index].src = 0;
|
2021-11-16 12:10:06 +08:00
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (lookup_is_duplicate_symbol(table, rela->sym->name, objname,
|
|
|
|
|
+ symbol.sympos)) {
|
|
|
|
|
+ struct lookup_refsym refsym;
|
2020-02-27 17:15:29 -05:00
|
|
|
+
|
2021-11-16 12:10:06 +08:00
|
|
|
+ if (lookup_ref_symbol_offset(table, rela->sym,
|
|
|
|
|
+ &refsym, objname, &ref_offset))
|
|
|
|
|
+ ERROR("unresolvable ambiguity on symbol %s\n",
|
|
|
|
|
+ rela->sym->name);
|
2020-02-27 17:15:29 -05:00
|
|
|
+
|
2021-11-16 12:10:06 +08:00
|
|
|
+ /* add rela to fill in ref_name field */
|
|
|
|
|
+ ALLOC_LINK(rela2, &krela_sec->rela->relas);
|
|
|
|
|
+ rela2->sym = strsym;
|
2023-01-30 16:10:43 +08:00
|
|
|
+ rela2->type = absolute_rela_type(kelf);
|
2021-11-16 12:10:06 +08:00
|
|
|
+ rela2->addend = offset_of_string(&kelf->strings,
|
|
|
|
|
+ refsym.name);
|
|
|
|
|
+ rela2->offset = (unsigned int)(index * sizeof(*krelas) +
|
2020-05-11 14:59:12 +08:00
|
|
|
+ offsetof(struct kpatch_relocation, ref_name));
|
2020-02-27 17:15:29 -05:00
|
|
|
+ }
|
2021-11-16 12:10:06 +08:00
|
|
|
+
|
|
|
|
|
ksyms[index].sympos = symbol.sympos;
|
2020-02-27 17:15:29 -05:00
|
|
|
ksyms[index].type = rela->sym->type;
|
|
|
|
|
ksyms[index].bind = rela->sym->bind;
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -3604,7 +3636,8 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
|
2020-02-27 17:15:29 -05:00
|
|
|
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
|
|
|
|
|
rela2->sym = strsym;
|
2023-01-30 16:10:43 +08:00
|
|
|
rela2->type = absolute_rela_type(kelf);
|
2020-02-27 17:15:29 -05:00
|
|
|
- rela2->addend = offset_of_string(&kelf->strings, rela->sym->name);
|
2020-09-12 05:45:06 -04:00
|
|
|
+ rela2->addend = offset_of_string(&kelf->strings,
|
|
|
|
|
+ strndup(rela->sym->name, KSYM_NAME_LEN-1));
|
2020-05-11 14:59:12 +08:00
|
|
|
rela2->offset = (unsigned int)(index * sizeof(*ksyms) + \
|
|
|
|
|
offsetof(struct kpatch_symbol, name));
|
2020-02-27 17:15:29 -05:00
|
|
|
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -3623,6 +3656,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
|
2020-02-27 17:15:29 -05:00
|
|
|
krelas[index].addend = rela->addend;
|
|
|
|
|
krelas[index].type = rela->type;
|
2021-11-16 12:10:06 +08:00
|
|
|
krelas[index].external = !vmlinux && symbol.exported;
|
2020-02-27 17:15:29 -05:00
|
|
|
+ krelas[index].ref_offset = ref_offset;
|
|
|
|
|
|
|
|
|
|
/* add rela to fill in krelas[index].dest field */
|
|
|
|
|
ALLOC_LINK(rela2, &krela_sec->rela->relas);
|
|
|
|
|
diff --git a/kpatch-build/create-klp-module.c b/kpatch-build/create-klp-module.c
|
2024-03-02 00:18:20 +08:00
|
|
|
index c50f0dd..89d37c8 100644
|
2020-02-27 17:15:29 -05:00
|
|
|
--- a/kpatch-build/create-klp-module.c
|
|
|
|
|
+++ b/kpatch-build/create-klp-module.c
|
|
|
|
|
@@ -38,7 +38,9 @@ enum loglevel loglevel = NORMAL;
|
|
|
|
|
*/
|
|
|
|
|
static struct symbol *find_or_add_ksym_to_symbols(struct kpatch_elf *kelf,
|
|
|
|
|
struct section *ksymsec,
|
|
|
|
|
- char *strings, int offset)
|
|
|
|
|
+ char *strings, int offset,
|
|
|
|
|
+ char *ref_name,
|
|
|
|
|
+ long ref_offset)
|
|
|
|
|
{
|
|
|
|
|
struct kpatch_symbol *ksyms, *ksym;
|
|
|
|
|
struct symbol *sym;
|
|
|
|
|
@@ -67,9 +69,14 @@ static struct symbol *find_or_add_ksym_to_symbols(struct kpatch_elf *kelf,
|
|
|
|
|
|
|
|
|
|
objname = strings + rela->addend;
|
|
|
|
|
|
2021-11-16 12:10:06 +08:00
|
|
|
- snprintf(pos, 32, "%lu", ksym->sympos);
|
2020-02-27 17:15:29 -05:00
|
|
|
/* .klp.sym.objname.name,pos */
|
|
|
|
|
- snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos);
|
|
|
|
|
+ if (!ref_name) {
|
2021-11-16 12:10:06 +08:00
|
|
|
+ snprintf(pos, 32, "%lu", ksym->sympos);
|
2020-02-27 17:15:29 -05:00
|
|
|
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ snprintf(pos, 32, "%ld", ref_offset);
|
|
|
|
|
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s-%s,%s", objname, ref_name, pos);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
/* Look for an already allocated symbol */
|
|
|
|
|
list_for_each_entry(sym, &kelf->symbols, list) {
|
|
|
|
|
@@ -176,6 +183,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
|
|
|
|
|
struct rela *rela;
|
|
|
|
|
char *objname;
|
2020-05-11 14:59:12 +08:00
|
|
|
unsigned int nr, index, offset, dest_off;
|
2020-09-12 05:45:06 -04:00
|
|
|
+ char *ref_name;
|
2020-02-27 17:15:29 -05:00
|
|
|
|
|
|
|
|
krelas = krelasec->data->d_buf;
|
2020-05-11 14:59:12 +08:00
|
|
|
nr = (unsigned int)(krelasec->data->d_size / sizeof(*krelas));
|
2020-02-27 17:15:29 -05:00
|
|
|
@@ -200,6 +208,15 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
|
|
|
|
|
|
|
|
|
|
objname = strings + rela->addend;
|
|
|
|
|
|
|
|
|
|
+ /* Get the unique ref_name */
|
|
|
|
|
+ rela = find_rela_by_offset(krelasec->rela,
|
2020-09-12 05:45:06 -04:00
|
|
|
+ (unsigned int)(offset + offsetof(struct kpatch_relocation,
|
|
|
|
|
+ ref_name)));
|
2020-02-27 17:15:29 -05:00
|
|
|
+ if (!rela)
|
|
|
|
|
+ ref_name = NULL;
|
2020-09-12 05:45:06 -04:00
|
|
|
+ else
|
2020-02-27 17:15:29 -05:00
|
|
|
+ ref_name = strings + rela->addend;
|
|
|
|
|
+
|
|
|
|
|
/* Get the .kpatch.symbol entry for the rela src */
|
|
|
|
|
rela = find_rela_by_offset(krelasec->rela,
|
2020-05-11 14:59:12 +08:00
|
|
|
(unsigned int)(offset + offsetof(struct kpatch_relocation, ksym)));
|
2020-09-12 05:45:06 -04:00
|
|
|
@@ -208,7 +225,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
|
2020-02-27 17:15:29 -05:00
|
|
|
|
|
|
|
|
/* Create (or find) a klp symbol from the rela src entry */
|
2020-09-12 05:45:06 -04:00
|
|
|
sym = find_or_add_ksym_to_symbols(kelf, ksymsec, strings,
|
2020-05-11 14:59:12 +08:00
|
|
|
- (unsigned int)rela->addend);
|
2020-09-12 05:45:06 -04:00
|
|
|
+ (unsigned int)rela->addend, ref_name, krelas[index].ref_offset);
|
2020-02-27 17:15:29 -05:00
|
|
|
if (!sym)
|
|
|
|
|
ERROR("error finding or adding ksym to symtab");
|
|
|
|
|
|
|
|
|
|
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
|
2024-03-02 00:18:20 +08:00
|
|
|
index 8bd721b..0567523 100755
|
2020-02-27 17:15:29 -05:00
|
|
|
--- a/kpatch-build/kpatch-build
|
|
|
|
|
+++ b/kpatch-build/kpatch-build
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -1366,6 +1366,18 @@ for i in $FILES; do
|
2020-02-27 17:15:29 -05:00
|
|
|
SYMTAB="${KOBJFILE_PATH}.symtab"
|
2023-01-30 16:10:43 +08:00
|
|
|
SYMVERS_FILE="$BUILDDIR/Module.symvers"
|
2020-02-27 17:15:29 -05:00
|
|
|
|
|
|
|
|
+ unset KCFLAGS
|
|
|
|
|
+ remove_patches
|
2023-01-30 16:10:43 +08:00
|
|
|
+ cd "$BUILDDIR" || die
|
2020-02-27 17:15:29 -05:00
|
|
|
+ if [ -z "$USERMODBUILDDIR" ];then
|
2021-11-16 12:10:06 +08:00
|
|
|
+ make "-j$CPUS" $TARGETS 2>&1 | logger || die
|
2020-02-27 17:15:29 -05:00
|
|
|
+ else
|
2021-11-16 12:10:06 +08:00
|
|
|
+ make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" $USERMODFLAGS "-j$CPUS" $TARGETS 2>&1 | logger || die
|
2020-02-27 17:15:29 -05:00
|
|
|
+ fi
|
|
|
|
|
+ cp ${KOBJFILE} ${KOBJFILE_PATH}
|
|
|
|
|
+ apply_patches
|
|
|
|
|
+ cd "$TEMPDIR" || die
|
|
|
|
|
+
|
|
|
|
|
if [ "$OOT_MODULE" == "yes" ];then
|
2024-03-02 00:18:20 +08:00
|
|
|
MODBUILDDIR="/lib/modules/$ARCHVERSION/build/"
|
2020-02-27 17:15:29 -05:00
|
|
|
SYMVERS_FILE="$TEMPDIR/Module.symvers"
|
|
|
|
|
diff --git a/kpatch-build/kpatch-intermediate.h b/kpatch-build/kpatch-intermediate.h
|
2021-11-16 12:10:06 +08:00
|
|
|
index 2036cb3..2589959 100644
|
2020-02-27 17:15:29 -05:00
|
|
|
--- a/kpatch-build/kpatch-intermediate.h
|
|
|
|
|
+++ b/kpatch-build/kpatch-intermediate.h
|
|
|
|
|
@@ -39,6 +39,8 @@ struct kpatch_relocation {
|
2020-05-11 14:59:12 +08:00
|
|
|
long addend;
|
2020-02-27 17:15:29 -05:00
|
|
|
char *objname; /* object to which this rela applies to */
|
|
|
|
|
struct kpatch_symbol *ksym;
|
2020-09-12 05:45:06 -04:00
|
|
|
+ char *ref_name;
|
|
|
|
|
+ long ref_offset;
|
2020-02-27 17:15:29 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct kpatch_arch {
|
|
|
|
|
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
|
2024-03-02 00:18:20 +08:00
|
|
|
index 8905a1d..9eb3e73 100644
|
2020-02-27 17:15:29 -05:00
|
|
|
--- a/kpatch-build/lookup.c
|
|
|
|
|
+++ b/kpatch-build/lookup.c
|
2021-11-16 12:10:06 +08:00
|
|
|
@@ -45,6 +45,7 @@ struct object_symbol {
|
2020-02-27 17:15:29 -05:00
|
|
|
unsigned long size;
|
|
|
|
|
char *name;
|
|
|
|
|
int type, bind;
|
|
|
|
|
+ int sec_index;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct export_symbol {
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -327,6 +328,7 @@ static void symtab_read(struct lookup_table *table, char *path)
|
2020-02-27 17:15:29 -05:00
|
|
|
|
2021-11-16 12:10:06 +08:00
|
|
|
table->obj_syms[i].addr = addr;
|
2020-02-27 17:15:29 -05:00
|
|
|
table->obj_syms[i].size = strtoul(size, NULL, 0);
|
|
|
|
|
+ table->obj_syms[i].sec_index = atoi(ndx);
|
|
|
|
|
|
|
|
|
|
if (!strcmp(bind, "LOCAL")) {
|
|
|
|
|
table->obj_syms[i].bind = STB_LOCAL;
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -487,6 +489,17 @@ static bool lookup_local_symbol(struct lookup_table *table,
|
2021-11-16 12:10:06 +08:00
|
|
|
if (sym->bind == STB_LOCAL && !strcmp(sym->name,
|
|
|
|
|
lookup_sym->name))
|
|
|
|
|
sympos++;
|
2020-02-27 17:15:29 -05:00
|
|
|
+ else {
|
2020-09-12 05:45:06 -04:00
|
|
|
+ /*
|
|
|
|
|
+ * symbol name longer than KSYM_NAME_LEN will be truncated
|
2020-02-27 17:15:29 -05:00
|
|
|
+ * by kernel, so we can not find it using its original
|
|
|
|
|
+ * name. we need to add pos for symbols which have same
|
2020-09-12 05:45:06 -04:00
|
|
|
+ * KSYM_NAME_LEN-1 long prefix.
|
|
|
|
|
+ */
|
2021-11-16 12:10:06 +08:00
|
|
|
+ if (strlen(lookup_sym->name) >= KSYM_NAME_LEN-1 &&
|
|
|
|
|
+ !strncmp(sym->name, lookup_sym->name, KSYM_NAME_LEN-1))
|
|
|
|
|
+ sympos++;
|
2020-02-27 17:15:29 -05:00
|
|
|
+ }
|
|
|
|
|
|
2021-11-16 12:10:06 +08:00
|
|
|
if (lookup_sym->lookup_table_file_sym == sym) {
|
2020-02-27 17:15:29 -05:00
|
|
|
in_file = 1;
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -557,11 +570,22 @@ static bool lookup_global_symbol(struct lookup_table *table, char *name,
|
2020-02-27 17:15:29 -05:00
|
|
|
{
|
|
|
|
|
struct object_symbol *sym;
|
|
|
|
|
int i;
|
2021-11-16 12:10:06 +08:00
|
|
|
+ unsigned long sympos = 0;
|
2020-02-27 17:15:29 -05:00
|
|
|
|
|
|
|
|
memset(result, 0, sizeof(*result));
|
|
|
|
|
for_each_obj_symbol(i, sym, table) {
|
2021-11-16 12:10:06 +08:00
|
|
|
-+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK
|
|
|
|
|
-+ || sym->bind == STB_GNU_UNIQUE) &&
|
2020-09-12 05:45:06 -04:00
|
|
|
+ /*
|
|
|
|
|
+ * symbol name longer than KSYM_NAME_LEN will be truncated
|
2020-02-27 17:15:29 -05:00
|
|
|
+ * by kernel, so we can not find it using its original
|
|
|
|
|
+ * name. we need to add pos for symbols which have same
|
2020-09-12 05:45:06 -04:00
|
|
|
+ * KSYM_NAME_LEN-1 long prefix.
|
|
|
|
|
+ */
|
2020-02-27 17:15:29 -05:00
|
|
|
+ if (strlen(name) >= KSYM_NAME_LEN-1 &&
|
|
|
|
|
+ !strncmp(sym->name, name, KSYM_NAME_LEN-1))
|
2021-11-16 12:10:06 +08:00
|
|
|
+ sympos++;
|
2020-02-27 17:15:29 -05:00
|
|
|
+
|
2021-11-16 12:10:06 +08:00
|
|
|
+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK
|
|
|
|
|
+ || sym->bind == STB_GNU_UNIQUE) &&
|
2020-02-27 17:15:29 -05:00
|
|
|
!strcmp(sym->name, name)) {
|
2021-11-16 12:10:06 +08:00
|
|
|
|
|
|
|
|
if (result->objname)
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -570,7 +594,7 @@ static bool lookup_global_symbol(struct lookup_table *table, char *name,
|
2021-11-16 12:10:06 +08:00
|
|
|
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);
|
2020-02-27 17:15:29 -05:00
|
|
|
}
|
2024-03-02 00:18:20 +08:00
|
|
|
@@ -590,3 +614,132 @@ bool lookup_symbol(struct lookup_table *table, struct symbol *sym,
|
2020-02-27 17:15:29 -05:00
|
|
|
|
2021-11-16 12:10:06 +08:00
|
|
|
return lookup_exported_symbol(table, sym->name, result);
|
|
|
|
|
}
|
|
|
|
|
+
|
2020-02-27 17:15:29 -05:00
|
|
|
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name,
|
|
|
|
|
+ char *objname, unsigned long pos)
|
|
|
|
|
+{
|
|
|
|
|
+ struct object_symbol *sym;
|
|
|
|
|
+ int i, count = 0;
|
|
|
|
|
+ char posstr[32], buf[256];
|
|
|
|
|
+
|
|
|
|
|
+ for_each_obj_symbol(i, sym, table)
|
|
|
|
|
+ if (!strcmp(sym->name, name)) {
|
|
|
|
|
+ count++;
|
|
|
|
|
+ if (count > 1)
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
2020-09-12 05:45:06 -04:00
|
|
|
+ /*
|
|
|
|
|
+ * symbol name longer than KSYM_NAME_LEN will be truncated
|
2020-02-27 17:15:29 -05:00
|
|
|
+ * by kernel, so we can not find it using its original
|
|
|
|
|
+ * name. Here, we consider these long name symbol as duplicated
|
2020-09-12 05:45:06 -04:00
|
|
|
+ * symbols. since create_klp_module will create symbol name
|
2020-02-27 17:15:29 -05:00
|
|
|
+ * format like .klp.sym.objname.symbol,pos, so we consider name
|
2020-09-12 05:45:06 -04:00
|
|
|
+ * length longer than KSYM_NAME_LEN-1 bytes as duplicated symbol
|
|
|
|
|
+ */
|
2020-02-27 17:15:29 -05:00
|
|
|
+ snprintf(posstr, 32, "%lu", pos);
|
|
|
|
|
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, posstr);
|
|
|
|
|
+ if (strlen(buf) >= KSYM_NAME_LEN-1)
|
|
|
|
|
+ return 1;
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
2021-11-16 12:10:06 +08:00
|
|
|
+struct object_symbol *lookup_find_symbol(struct lookup_table *table,
|
|
|
|
|
+ struct symbol *lookup_sym)
|
2020-02-27 17:15:29 -05:00
|
|
|
+{
|
|
|
|
|
+ struct object_symbol *sym;
|
|
|
|
|
+ unsigned long pos = 0;
|
|
|
|
|
+ int i, match = 0, in_file = 0;
|
|
|
|
|
+
|
2021-11-16 12:10:06 +08:00
|
|
|
+ if (!lookup_sym->lookup_table_file_sym)
|
2020-02-27 17:15:29 -05:00
|
|
|
+ return NULL;
|
|
|
|
|
+
|
|
|
|
|
+ for_each_obj_symbol(i, sym, table) {
|
2021-11-16 12:10:06 +08:00
|
|
|
+ if (sym->bind == STB_LOCAL && !strcmp(sym->name, lookup_sym->name))
|
2020-02-27 17:15:29 -05:00
|
|
|
+ pos++;
|
|
|
|
|
+
|
2021-11-16 12:10:06 +08:00
|
|
|
+ if (lookup_sym->lookup_table_file_sym == sym) {
|
2020-02-27 17:15:29 -05:00
|
|
|
+ in_file = 1;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!in_file)
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ if (sym->type == STT_FILE)
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
2021-11-16 12:10:06 +08:00
|
|
|
+ if (sym->bind == STB_LOCAL && !strcmp(sym->name, lookup_sym->name)) {
|
2020-02-27 17:15:29 -05:00
|
|
|
+ match = 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!match) {
|
|
|
|
|
+ for_each_obj_symbol(i, sym, table) {
|
|
|
|
|
+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) &&
|
2021-11-16 12:10:06 +08:00
|
|
|
+ !strcmp(sym->name, lookup_sym->name)) {
|
2020-02-27 17:15:29 -05:00
|
|
|
+ return sym;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return sym;
|
|
|
|
|
+}
|
|
|
|
|
+
|
2021-11-16 12:10:06 +08:00
|
|
|
+int lookup_ref_symbol_offset(struct lookup_table *table,
|
|
|
|
|
+ struct symbol *lookup_sym,
|
2020-02-27 17:15:29 -05:00
|
|
|
+ struct lookup_refsym *refsym,
|
|
|
|
|
+ char *objname, long *offset)
|
|
|
|
|
+{
|
|
|
|
|
+ struct object_symbol *orig_sym, *sym;
|
|
|
|
|
+ int i;
|
|
|
|
|
+
|
2021-11-16 12:10:06 +08:00
|
|
|
+ orig_sym = lookup_find_symbol(table, lookup_sym);
|
2020-02-27 17:15:29 -05:00
|
|
|
+ if (!orig_sym)
|
|
|
|
|
+ ERROR("lookup_ref_symbol_offset");
|
|
|
|
|
+ memset(refsym, 0, sizeof(*refsym));
|
|
|
|
|
+
|
|
|
|
|
+ /*find a unique symbol in the same section first*/
|
|
|
|
|
+ for_each_obj_symbol(i, sym, table) {
|
2021-11-16 12:10:06 +08:00
|
|
|
+ if (!strcmp(sym->name, lookup_sym->name) || sym->type == STT_FILE ||
|
2020-02-27 17:15:29 -05:00
|
|
|
+ sym->sec_index != orig_sym->sec_index ||
|
|
|
|
|
+ strchr(sym->name, '.'))
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
|
|
|
|
|
+ refsym->name = sym->name;
|
2021-11-16 12:10:06 +08:00
|
|
|
+ refsym->addr = sym->addr;
|
|
|
|
|
+ *offset = (long)orig_sym->addr- (long)sym->addr;
|
2020-02-27 17:15:29 -05:00
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
2021-11-16 12:10:06 +08:00
|
|
|
+/*
|
|
|
|
|
+ * 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;
|
|
|
|
|
+}
|
2020-02-27 17:15:29 -05:00
|
|
|
diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h
|
2021-11-16 12:10:06 +08:00
|
|
|
index e1277f1..21aceb4 100644
|
2020-02-27 17:15:29 -05:00
|
|
|
--- a/kpatch-build/lookup.h
|
|
|
|
|
+++ b/kpatch-build/lookup.h
|
2021-11-16 12:10:06 +08:00
|
|
|
@@ -4,6 +4,8 @@
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include "kpatch-elf.h"
|
2020-02-27 17:15:29 -05:00
|
|
|
|
|
|
|
|
+#define KSYM_NAME_LEN 128
|
|
|
|
|
+
|
|
|
|
|
struct lookup_table;
|
|
|
|
|
|
|
|
|
|
struct lookup_result {
|
2021-11-16 12:10:06 +08:00
|
|
|
@@ -14,10 +16,23 @@ struct lookup_result {
|
|
|
|
|
bool global, exported;
|
2020-02-27 17:15:29 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
+struct lookup_refsym {
|
|
|
|
|
+ char *name;
|
2021-11-16 12:10:06 +08:00
|
|
|
+ unsigned long addr;
|
2020-02-27 17:15:29 -05:00
|
|
|
+};
|
|
|
|
|
+
|
2021-11-16 12:10:06 +08:00
|
|
|
struct lookup_table *lookup_open(char *symtab_path, char *objname,
|
|
|
|
|
char *symvers_path, struct kpatch_elf *kelf);
|
2020-02-27 17:15:29 -05:00
|
|
|
void lookup_close(struct lookup_table *table);
|
2021-11-16 12:10:06 +08:00
|
|
|
bool lookup_symbol(struct lookup_table *table, struct symbol *sym,
|
|
|
|
|
struct lookup_result *result);
|
2020-02-27 17:15:29 -05:00
|
|
|
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name,
|
|
|
|
|
+ char *objname, unsigned long pos);
|
2021-11-16 12:10:06 +08:00
|
|
|
+int lookup_ref_symbol_offset(struct lookup_table *table,
|
|
|
|
|
+ struct symbol *lookup_sym,
|
2020-09-12 05:45:06 -04:00
|
|
|
+ struct lookup_refsym *refsym, char *objname,
|
2020-02-27 17:15:29 -05:00
|
|
|
+ long *offset);
|
2021-11-16 12:10:06 +08:00
|
|
|
+unsigned long get_vmlinux_duplicate_symbol_pos(struct lookup_table *table, char *name,
|
|
|
|
|
+ unsigned long addr);
|
2020-02-27 17:15:29 -05:00
|
|
|
|
|
|
|
|
#endif /* _LOOKUP_H_ */
|
|
|
|
|
--
|
2023-01-30 16:10:43 +08:00
|
|
|
2.33.0
|
2020-09-12 05:45:06 -04:00
|
|
|
|