From ec5c36ca4f00918ffbca5ec89d7afa50147c06fa Mon Sep 17 00:00:00 2001 From: Gou Hao Date: Sun, 17 Sep 2023 11:18:43 +0800 Subject: [PATCH] livepatch: support new style symbol format uos inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I81SSY ----------------------- Kpatch add some work around for symbols which have same name in one module or have length longger than KSYM_NAME_LEN(128 bytes). It defined a new style symbol format: .klp.sym.sym_objname-ref_name,ref_offset kernel livepatch does not support this symbol style currently, sometimes hotpatch can not be applied, log: kernel: livepatch: symbol .klp.sym.vmlinux-set_cpu_boot_mode_flag,-8546056 has an incorrectly formatted name So add support for new style format. Signed-off-by: Gou Hao --- kernel/livepatch/core.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 8768ec1bddf3..cc1cf3104d22 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -275,8 +275,10 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab, #endif Elf_Sym *sym; unsigned long sympos, addr; + long ref_offset; bool sym_vmlinux; bool sec_vmlinux = !strcmp(sec_objname, "vmlinux"); + bool new_style; /* * Since the field widths for sym_objname and sym_name in the sscanf() @@ -304,10 +306,19 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab, return -EINVAL; } - /* Format: .klp.sym.sym_objname.sym_name,sympos */ - cnt = sscanf(strtab + sym->st_name, - ".klp.sym.%55[^.].%127[^,],%lu", - sym_objname, sym_name, &sympos); + new_style = !!strchr(strtab + sym->st_name, '-'); + if (likely(!new_style)) { + /* Format: .klp.sym.sym_objname.sym_name,sympos */ + cnt = sscanf(strtab + sym->st_name, + ".klp.sym.%55[^.].%127[^,],%lu", + sym_objname, sym_name, &sympos); + } else { + /* Format: .klp.sym.sym_objname-ref_name,ref_offset */ + cnt = sscanf(strtab + sym->st_name, + ".klp.sym.%55[^-]-%127[^,],%ld", + sym_objname, sym_name, &ref_offset); + } + if (cnt != 3) { pr_err("symbol %s has an incorrectly formatted name\n", strtab + sym->st_name); @@ -328,11 +339,21 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab, return -EINVAL; } - /* klp_find_object_symbol() treats a NULL objname as vmlinux */ - ret = klp_find_object_symbol(sym_vmlinux ? NULL : sym_objname, - sym_name, sympos, &addr); - if (ret) - return ret; + if (likely(!new_style)) { + /* klp_find_object_symbol() treats a NULL objname as vmlinux */ + ret = klp_find_object_symbol(sym_vmlinux ? NULL : sym_objname, + sym_name, sympos, &addr); + if (ret) + return ret; + } else { + addr = kallsyms_lookup_name(sym_name); + if (!addr) { + pr_err("can not get %s's address\n", sym_name); + return -EINVAL; + } + + addr += ref_offset; + } sym->st_value = addr; } -- Gitee