diff --git a/xen/common/vsprintf.c b/xen/common/vsprintf.c index 18d2634693..70e1edf562 100644 --- a/xen/common/vsprintf.c +++ b/xen/common/vsprintf.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -354,6 +355,17 @@ static char *pointer(char *str, char *end, const char **fmt_ptr, str = number(str, end, sym_size, 16, -1, -1, SPECIAL); } + /* + * namebuf contents and s for core hypervisor are same but for xSplice + * payloads they differ (namebuf contains the name of the payload). + */ + if ( namebuf != s ) + { + str = string(str, end, " [", -1, -1, 0); + str = string(str, end, namebuf, -1, -1, 0); + str = string(str, end, "]", -1, -1, 0); + } + return str; } diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c index 3d56c04946..e7872c62a1 100644 --- a/xen/common/xsplice.c +++ b/xen/common/xsplice.c @@ -14,7 +14,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -31,10 +33,9 @@ static LIST_HEAD(payload_list); /* * Patches which have been applied. Need RCU in case we crash (and then - * traps code would iterate via applied_list) when adding entries on the list. - * - * Note: There are no 'rcu_applied_lock' as we don't iterate yet the list. + * traps code would iterate via applied_list) when adding entries onthe list. */ +static DEFINE_RCU_READ_LOCK(rcu_applied_lock); static LIST_HEAD(applied_list); static unsigned int payload_cnt; @@ -56,6 +57,8 @@ struct payload { unsigned int nfuncs; /* Nr of functions to patch. */ const struct xsplice_symbol *symtab; /* All symbols. */ const char *strtab; /* Pointer to .strtab. */ + struct virtual_region region; /* symbol, bug.frame patching and + exception table (x86). */ unsigned int nsyms; /* Nr of entries in .strtab and symbols. */ char name[XEN_XSPLICE_NAME_SIZE]; /* Name of it. */ }; @@ -139,6 +142,55 @@ unsigned long xsplice_symbols_lookup_by_name(const char *symname) return 0; } +static const char *xsplice_symbols_lookup(unsigned long addr, + unsigned long *symbolsize, + unsigned long *offset, + char *namebuf) +{ + const struct payload *data; + unsigned int i, best; + const void *va = (const void *)addr; + const char *n = NULL; + + /* + * Only RCU locking since this list is only ever changed during apply + * or revert context. And in case it dies there we need an safe list. + */ + rcu_read_lock(&rcu_applied_lock); + list_for_each_entry_rcu ( data, &applied_list, applied_list ) + { + if ( va < data->text_addr || + va >= (data->text_addr + data->text_size) ) + continue; + + best = UINT_MAX; + + for ( i = 0; i < data->nsyms; i++ ) + { + if ( data->symtab[i].value <= addr && + (best == UINT_MAX || + data->symtab[best].value < data->symtab[i].value) ) + best = i; + } + + if ( best == UINT_MAX ) + break; + + if ( symbolsize ) + *symbolsize = data->symtab[best].size; + if ( offset ) + *offset = addr - data->symtab[best].value; + if ( namebuf ) + strlcpy(namebuf, data->name, KSYM_NAME_LEN); + + n = data->symtab[best].name; + break; + } + rcu_read_unlock(&rcu_applied_lock); + + return n; +} + static struct payload *find_payload(const char *name) { struct payload *data, *found = NULL; @@ -364,6 +416,7 @@ static int prepare_payload(struct payload *payload, const struct xsplice_elf_sec *sec; unsigned int i; struct xsplice_patch_func *f; + struct virtual_region *region; sec = xsplice_elf_sec_by_name(elf, ELF_XSPLICE_FUNC); ASSERT(sec); @@ -420,6 +473,13 @@ static int prepare_payload(struct payload *payload, } } + /* Setup the virtual region with proper data. */ + region = &payload->region; + + region->symbols_lookup = xsplice_symbols_lookup; + region->start = payload->text_addr; + region->end = payload->text_addr + payload->text_size; + return 0; } @@ -496,6 +556,7 @@ static int build_symbol_table(struct payload *payload, if ( is_payload_symbol(elf, elf->sym + i) ) { symtab[nsyms].name = strtab + strtab_len; + symtab[nsyms].size = elf->sym[i].sym->st_size; symtab[nsyms].value = elf->sym[i].sym->st_value; symtab[nsyms].new_symbol = 0; /* May be overwritten below. */ strtab_len += strlcpy(strtab + strtab_len, elf->sym[i].name, @@ -779,6 +840,7 @@ static int apply_payload(struct payload *data) * The applied_list is iterated by the trap code. */ list_add_tail_rcu(&data->applied_list, &applied_list); + register_virtual_region(&data->region); return 0; } @@ -801,6 +863,7 @@ static int revert_payload(struct payload *data) * The applied_list is iterated by the trap code. */ list_del_rcu(&data->applied_list); + unregister_virtual_region(&data->region); return 0; } diff --git a/xen/include/xen/xsplice.h b/xen/include/xen/xsplice.h index 0a6020df6a..331c383926 100644 --- a/xen/include/xen/xsplice.h +++ b/xen/include/xen/xsplice.h @@ -22,6 +22,7 @@ struct xen_sysctl_xsplice_op; struct xsplice_symbol { const char *name; unsigned long value; + unsigned int size; bool_t new_symbol; };