diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h index 953ac5e..d0d6aeb 100644 --- a/kmod/patch/kpatch-patch.h +++ b/kmod/patch/kpatch-patch.h @@ -27,6 +27,7 @@ struct kpatch_patch_func { unsigned long new_size; unsigned long old_addr; unsigned long old_size; + unsigned long sympos; char *name; char *objname; }; @@ -35,6 +36,7 @@ struct kpatch_patch_dynrela { unsigned long dest; unsigned long src; unsigned long type; + unsigned long sympos; char *name; char *objname; int external; diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c index 34d7fd2..327ec93 100644 --- a/kmod/patch/livepatch-patch-hook.c +++ b/kmod/patch/livepatch-patch-hook.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -237,7 +238,11 @@ static int __init patch_init(void) lfunc = &lfuncs[j]; lfunc->old_name = func->kfunc->name; lfunc->new_func = (void *)func->kfunc->new_addr; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) + lfunc->old_sympos = func->kfunc->sympos; +#else lfunc->old_addr = func->kfunc->old_addr; +#endif j++; } @@ -250,7 +255,11 @@ static int __init patch_init(void) list_for_each_entry(reloc, &object->relocs, list) { lreloc = &lrelocs[j]; lreloc->loc = reloc->kdynrela->dest; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) + lreloc->sympos = reloc->kdynrela->sympos; +#else lreloc->val = reloc->kdynrela->src; +#endif lreloc->type = reloc->kdynrela->type; lreloc->name = reloc->kdynrela->name; lreloc->addend = reloc->kdynrela->addend; diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 93ed193..34a8ee2 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -2539,6 +2539,7 @@ void kpatch_create_patches_sections(struct kpatch_elf *kelf, funcs[index].old_addr = result.value; funcs[index].old_size = result.size; funcs[index].new_size = sym->sym.st_size; + funcs[index].sympos = result.pos; /* * Add a relocation that will populate @@ -2715,6 +2716,7 @@ void kpatch_create_dynamic_rela_sections(struct kpatch_elf *kelf, dynrelas[index].addend = rela->addend; dynrelas[index].type = rela->type; dynrelas[index].external = external; + dynrelas[index].sympos = result.pos; /* add rela to fill in dest field */ ALLOC_LINK(dynrela, &relasec->relas); diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c index 5a43dd1..b411326 100644 --- a/kpatch-build/lookup.c +++ b/kpatch-build/lookup.c @@ -148,6 +148,7 @@ int lookup_local_symbol(struct lookup_table *table, char *name, char *hint, { struct symbol *sym, *match = NULL; int i; + unsigned long pos = 0; char *curfile = NULL; memset(result, 0, sizeof(*result)); @@ -159,19 +160,30 @@ int lookup_local_symbol(struct lookup_table *table, char *name, char *hint, } else if (curfile) curfile = NULL; /* end hint file symbols */ } - if (!curfile) - continue; - if (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) { - if (match) - /* dup file+symbol, unresolvable ambiguity */ - return 1; - match = sym; + if (sym->bind == STB_LOCAL) { + if (sym->name && !strcmp(sym->name, name)) { + /* + * need to count any occurrence of the symbol + * name, unless we've already found a match + */ + if (!match) + pos++; + + if (!curfile) + continue; + + if (match) + /* dup file+symbol, unresolvable ambiguity */ + return 1; + match = sym; + } } } if (!match) return 1; + result->pos = pos; result->value = match->value; result->size = match->size; return 0; @@ -189,6 +201,7 @@ int lookup_global_symbol(struct lookup_table *table, char *name, !strcmp(sym->name, name)) { result->value = sym->value; result->size = sym->size; + result->pos = 0; /* always 0 for global symbols */ return 0; } @@ -220,9 +233,9 @@ static void find_this(struct lookup_table *table, char *sym, char *hint) else lookup_global_symbol(table, sym, &result); - printf("%s %s w/ %s hint at 0x%016lx len %lu\n", + printf("%s %s w/ %s hint at 0x%016lx len %lu pos %lu\n", hint ? "local" : "global", sym, hint ? hint : "no", - result.value, result.size); + result.value, result.size, result.pos); } int main(int argc, char **argv) diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h index cbb3dae..90b7767 100644 --- a/kpatch-build/lookup.h +++ b/kpatch-build/lookup.h @@ -6,6 +6,7 @@ struct lookup_table; struct lookup_result { unsigned long value; unsigned long size; + unsigned long pos; }; struct lookup_table *lookup_open(char *path);