|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v8.1 14/27] xsplice, symbols: Implement symbol name resolution on address.
>>> Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> 04/14/16 12:02 AM >>>
>--- a/xen/arch/x86/test/xen_hello_world.c
>+++ b/xen/arch/x86/test/xen_hello_world.c
>@@ -10,11 +10,14 @@
>static char hello_world_patch_this_fnc[] = "xen_extra_version";
>extern const char *xen_hello_world(void);
>
>+/* External symbol. */
>+extern const char *xen_extra_version(void);
To give a good example, I think this would better include the respective
header.
>struct xsplice_patch_func __section(".xsplice.funcs") xsplice_xen_hello_world
>= {
>.version = XSPLICE_PAYLOAD_VERSION,
>.name = hello_world_patch_this_fnc,
>.new_addr = (unsigned long)(xen_hello_world),
>- .old_addr = OLD_CODE,
>+ .old_addr = (unsigned long)(xen_extra_version),
Pointless parentheses (also btw on the new_addr initializer, which would be
nice to get fixed in the earlier patch).
>+unsigned long symbols_lookup_by_name(const char *symname)
>+{
>+ char name[KSYM_NAME_LEN + 1] = { 0 };
I continue to think that this initializer is pointless. And if this or a
variant filling
just the first byte was needed, then please be consistent with the rest of the
function and either use '\0' here or plain 0 in the other two relevant places.
>+ uint32_t symnum = 0;
>+ char type;
>+ uint64_t addr = 0;
Same here.
>+ int rc;
>+
>+ if ( symname == '\0' )
DYM *symname?
>@@ -51,6 +52,9 @@ struct payload {
>struct list_head applied_list; /* Linked to 'applied_list'. */
>struct xsplice_patch_func_internal *funcs; /* The array of functions
to patch. */
>unsigned int nfuncs; /* Nr of functions to patch. */
>+ struct xsplice_symbol *symtab; /* All symbols. */
>+ char *strtab; /* Pointer to .strtab. */
At least the latter of the two I'm convinced can be const.
>+unsigned long xsplice_symbols_lookup_by_name(const char *symname)
>+{
>+ struct payload *data;
const
>+ ASSERT(spin_is_locked(&payload_lock));
>+ list_for_each_entry ( data, &payload_list, list )
>+ {
>+ unsigned int i;
>+
>+ for ( i = 0; i < data->nsyms; i++ )
>+ {
>+ if ( !data->symtab[i].new_symbol )
>+ continue;
Do you need symbols other than those marked "new_symbol" past the loading
of the module? If not, wouldn't it be worthwhile to shrink the symbol table to
just
those, likely speeding up the lookup?
>@@ -379,11 +405,129 @@ static int prepare_payload(struct payload *payload,
>for ( j = 0; j < ARRAY_SIZE(f->u.pad); j++ )
>if ( f->u.pad[j] )
>return -EINVAL;
>+
>+ /* Lookup function's old address if not already resolved. */
>+ if ( !f->old_addr )
>+ {
>+ f->old_addr = (void *)symbols_lookup_by_name(f->name);
>+ if ( !f->old_addr )
>+ {
>+ f->old_addr = (void *)xsplice_symbols_lookup_by_name(f->name);
The two casts make me wonder whether the two functions shouldn't return
void *, and then whether struct xsplice_symbol's value field shouldn't then
perhaps be void * too.
>+ if ( !f->old_addr )
>+ {
>+ dprintk(XENLOG_ERR, XSPLICE "%s: Could not resolve old
>address of %s\n",
>+ elf->name, f->name);
>+ return -ENOENT;
>+ }
>+ }
>+ dprintk(XENLOG_DEBUG, XSPLICE "%s: Resolved old address %s =>
>%p\n",
>+ elf->name, f->name, f->old_addr);
>+ }
>}
>
>return 0;
>}
So one thing I'm realizing only now: Is there no support for using
<symbol>+<offset>
to fill ->old_addr?
>+static bool_t is_payload_symbol(const struct xsplice_elf *elf,
>+ const struct xsplice_elf_sym *sym)
>+{
>+ if ( sym->sym->st_shndx == SHN_UNDEF ||
>+ sym->sym->st_shndx >= elf->hdr->e_shnum )
>+ return 0;
>+
>+ return (elf->sec[sym->sym->st_shndx].sec->sh_flags & SHF_ALLOC) &&
>+ (ELF64_ST_TYPE(sym->sym->st_info) == STT_OBJECT ||
>+ ELF64_ST_TYPE(sym->sym->st_info) == STT_FUNC);
I don't recall having seen a reply to the question on not allowing STT_NOTYPE
here.
>+static int build_symbol_table(struct payload *payload,
>+ const struct xsplice_elf *elf)
>+{
>+ unsigned int i, j, nsyms = 0;
>+ size_t strtab_len = 0;
>+ struct xsplice_symbol *symtab;
>+ char *strtab;
>+
>+ ASSERT(payload->nfuncs);
>+
>+ /* Recall that section @0 is always NULL. */
>+ for ( i = 1; i < elf->nsym; i++ )
>+ {
>+ if ( is_payload_symbol(elf, elf->sym + i) )
>+ {
>+ nsyms++;
>+ strtab_len += strlen(elf->sym[i].name) + 1;
>+ }
>+ }
>+
>+ symtab = xmalloc_array(struct xsplice_symbol, nsyms);
>+ strtab = xmalloc_array(char, strtab_len);
>+
>+ if ( !strtab || !symtab )
>+ {
>+ xfree(strtab);
>+ xfree(symtab);
>+ return -ENOMEM;
>+ }
>+
>+ nsyms = 0;
>+ strtab_len = 0;
>+ for ( i = 1; i < elf->nsym; i++ )
>+ {
>+ 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; /* To be checked below. */
Why "checked"? The only thing happening further down is this possibly
getting overwritten with 1.
>@@ -274,9 +275,21 @@ int xsplice_elf_resolve_symbols(struct xsplice_elf *elf)
>break;
>
>case SHN_UNDEF:
>- dprintk(XENLOG_ERR, XSPLICE "%s: Unknown symbol: %s\n",
>- elf->name, elf->sym[i].name);
>- rc = -ENOENT;
>+ elf->sym[i].sym->st_value = (unsigned
>long)symbols_lookup_by_name(elf->sym[i].name);
With its current return value, the cast is pointless. But this makes clear that
either
here or above a cast is going to be needed. So perhaps just keep it as is,
except
for this unnecessary cast.
>+ if ( !elf->sym[i].sym->st_value )
>+ {
>+ elf->sym[i].sym->st_value = (unsigned
>long)xsplice_symbols_lookup_by_name(elf->sym[i].name);
And this one then, obviously.
>--- a/xen/include/xen/xsplice.h
>+++ b/xen/include/xen/xsplice.h
>@@ -46,8 +46,16 @@ struct xsplice_patch_func_internal {
>/* Convenience define for printk. */
>#define XSPLICE "xsplice: "
>
>+struct xsplice_symbol {
>+ const char *name;
>+ uint64_t value;
Either void * (see above) or unsigned long. No point in being 64-bit for e.g.
ARM32.
>+ size_t size;
I don't see this field being used for anything, it seems to only ever get
written to.
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |