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 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;

View File

@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/livepatch.h>
@ -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;

View File

@ -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);

View File

@ -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 (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 (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) {
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)

View File

@ -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);