Merge pull request #230 from jpoimboe/isra

create-diff-object: support gcc function name mangling
This commit is contained in:
Seth Jennings 2014-06-03 12:22:39 -05:00
commit 88cac305be
3 changed files with 85 additions and 0 deletions

View File

@ -224,6 +224,19 @@ struct symbol *find_symbol_by_name(struct list_head *list, const char *name)
return NULL;
}
struct symbol *find_symbol_by_name_prefix(struct list_head *list,
const char *name)
{
struct symbol *sym;
int namelen = strlen(name);
list_for_each_entry(sym, list, list)
if (!strncmp(sym->name, name, namelen))
return sym;
return NULL;
}
#define ALLOC_LINK(_new, _list) \
{ \
(_new) = malloc(sizeof(*(_new))); \
@ -681,6 +694,51 @@ void kpatch_check_program_headers(Elf *elf)
DIFF_FATAL("ELF contains program header");
}
/*
* When gcc makes compiler optimizations which affect a function's calling
* interface, it mangles the function's name. For example, sysctl_print_dir is
* renamed to sysctl_print_dir.isra.2. The problem is that the trailing number
* is chosen arbitrarily, and the patched version of the function may end up
* with a different trailing number. Rename any mangled patched functions to
* match their base counterparts.
*/
void kpatch_rename_mangled_functions(struct kpatch_elf *base,
struct kpatch_elf *patched)
{
struct symbol *sym, *basesym;
char *prefix, *dot;
list_for_each_entry(sym, &patched->symbols, list) {
if (sym->type != STT_FUNC)
continue;
if (!strstr(sym->name, ".isra.") &&
!strstr(sym->name, ".constprop."))
continue;
if (sym != sym->sec->sym)
ERROR("expected bundled section for %s\n", sym->name);
prefix = strdup(sym->name);
dot = strchr(prefix, '.');
*dot = '\0';
basesym = find_symbol_by_name_prefix(&base->symbols, prefix);
free(prefix);
if (!basesym)
continue;
if (!strcmp(sym->name, basesym->name))
continue;
log_debug("renaming %s to %s\n", sym->name, basesym->name);
sym->name = strdup(basesym->name);
sym->sec->name = strdup(basesym->sec->name);
if (sym->sec->rela)
sym->sec->rela->name = strdup(basesym->sec->rela->name);
}
}
void kpatch_correlate_elfs(struct kpatch_elf *kelf1, struct kpatch_elf *kelf2)
{
kpatch_correlate_sections(&kelf1->sections, &kelf2->sections);
@ -2004,6 +2062,8 @@ int main(int argc, char *argv[])
kpatch_check_program_headers(kelf_base->elf);
kpatch_check_program_headers(kelf_patched->elf);
kpatch_rename_mangled_functions(kelf_base, kelf_patched);
kpatch_correlate_elfs(kelf_base, kelf_patched);
/*
* After this point, we don't care about kelf_base anymore.

View File

@ -0,0 +1,13 @@
Index: src/kernel/time/timekeeping.c
===================================================================
--- src.orig/kernel/time/timekeeping.c
+++ src/kernel/time/timekeeping.c
@@ -480,6 +480,8 @@ void do_gettimeofday(struct timeval *tv)
{
struct timespec now;
+ if (!tv)
+ return;
getnstimeofday(&now);
tv->tv_sec = now.tv_sec;
tv->tv_usec = now.tv_nsec/1000;

View File

@ -0,0 +1,12 @@
Index: src/fs/proc/proc_sysctl.c
===================================================================
--- src.orig/fs/proc/proc_sysctl.c
+++ src/fs/proc/proc_sysctl.c
@@ -24,6 +24,7 @@ void proc_sys_poll_notify(struct ctl_tab
if (!poll)
return;
+ printk("kpatch-test: testing gcc .isra function name mangling\n");
atomic_inc(&poll->event);
wake_up_interruptible(&poll->wait);
}