Merge pull request #573 from arges/493

livepatch-patch-hook: add support for livepatch sympos structures
This commit is contained in:
Josh Poimboeuf 2016-02-17 08:57:06 -06:00
commit 83beb356ed
5 changed files with 36 additions and 9 deletions

View File

@ -27,6 +27,7 @@ struct kpatch_patch_func {
unsigned long new_size; unsigned long new_size;
unsigned long old_addr; unsigned long old_addr;
unsigned long old_size; unsigned long old_size;
unsigned long sympos;
char *name; char *name;
char *objname; char *objname;
}; };
@ -35,6 +36,7 @@ struct kpatch_patch_dynrela {
unsigned long dest; unsigned long dest;
unsigned long src; unsigned long src;
unsigned long type; unsigned long type;
unsigned long sympos;
char *name; char *name;
char *objname; char *objname;
int external; int external;

View File

@ -24,6 +24,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/version.h>
#include <linux/livepatch.h> #include <linux/livepatch.h>
@ -237,7 +238,11 @@ static int __init patch_init(void)
lfunc = &lfuncs[j]; lfunc = &lfuncs[j];
lfunc->old_name = func->kfunc->name; lfunc->old_name = func->kfunc->name;
lfunc->new_func = (void *)func->kfunc->new_addr; 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; lfunc->old_addr = func->kfunc->old_addr;
#endif
j++; j++;
} }
@ -250,7 +255,11 @@ static int __init patch_init(void)
list_for_each_entry(reloc, &object->relocs, list) { list_for_each_entry(reloc, &object->relocs, list) {
lreloc = &lrelocs[j]; lreloc = &lrelocs[j];
lreloc->loc = reloc->kdynrela->dest; 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; lreloc->val = reloc->kdynrela->src;
#endif
lreloc->type = reloc->kdynrela->type; lreloc->type = reloc->kdynrela->type;
lreloc->name = reloc->kdynrela->name; lreloc->name = reloc->kdynrela->name;
lreloc->addend = reloc->kdynrela->addend; lreloc->addend = reloc->kdynrela->addend;

View File

@ -2539,6 +2539,7 @@ void kpatch_create_patches_sections(struct kpatch_elf *kelf,
funcs[index].old_addr = result.value; funcs[index].old_addr = result.value;
funcs[index].old_size = result.size; funcs[index].old_size = result.size;
funcs[index].new_size = sym->sym.st_size; funcs[index].new_size = sym->sym.st_size;
funcs[index].sympos = result.pos;
/* /*
* Add a relocation that will populate * 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].addend = rela->addend;
dynrelas[index].type = rela->type; dynrelas[index].type = rela->type;
dynrelas[index].external = external; dynrelas[index].external = external;
dynrelas[index].sympos = result.pos;
/* add rela to fill in dest field */ /* add rela to fill in dest field */
ALLOC_LINK(dynrela, &relasec->relas); ALLOC_LINK(dynrela, &relasec->relas);

View File

@ -148,6 +148,7 @@ int lookup_local_symbol(struct lookup_table *table, char *name, char *hint,
{ {
struct symbol *sym, *match = NULL; struct symbol *sym, *match = NULL;
int i; int i;
unsigned long pos = 0;
char *curfile = NULL; char *curfile = NULL;
memset(result, 0, sizeof(*result)); memset(result, 0, sizeof(*result));
@ -159,19 +160,30 @@ int lookup_local_symbol(struct lookup_table *table, char *name, char *hint,
} else if (curfile) } else if (curfile)
curfile = NULL; /* end hint file symbols */ curfile = NULL; /* end hint file symbols */
} }
if (!curfile) if (sym->bind == STB_LOCAL) {
continue; if (sym->name && !strcmp(sym->name, name)) {
if (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) { /*
if (match) * need to count any occurrence of the symbol
/* dup file+symbol, unresolvable ambiguity */ * name, unless we've already found a match
return 1; */
match = sym; if (!match)
pos++;
if (!curfile)
continue;
if (match)
/* dup file+symbol, unresolvable ambiguity */
return 1;
match = sym;
}
} }
} }
if (!match) if (!match)
return 1; return 1;
result->pos = pos;
result->value = match->value; result->value = match->value;
result->size = match->size; result->size = match->size;
return 0; return 0;
@ -189,6 +201,7 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
!strcmp(sym->name, name)) { !strcmp(sym->name, name)) {
result->value = sym->value; result->value = sym->value;
result->size = sym->size; result->size = sym->size;
result->pos = 0; /* always 0 for global symbols */
return 0; return 0;
} }
@ -220,9 +233,9 @@ static void find_this(struct lookup_table *table, char *sym, char *hint)
else else
lookup_global_symbol(table, sym, &result); 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", hint ? "local" : "global", sym, hint ? hint : "no",
result.value, result.size); result.value, result.size, result.pos);
} }
int main(int argc, char **argv) int main(int argc, char **argv)

View File

@ -6,6 +6,7 @@ struct lookup_table;
struct lookup_result { struct lookup_result {
unsigned long value; unsigned long value;
unsigned long size; unsigned long size;
unsigned long pos;
}; };
struct lookup_table *lookup_open(char *path); struct lookup_table *lookup_open(char *path);