|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v5 13/28] xsplice, symbols: Implement symbol name resolution on address.
>>> On 24.03.16 at 21:00, <konrad.wilk@xxxxxxxxxx> wrote:
> --- a/xen/arch/x86/Makefile
> +++ b/xen/arch/x86/Makefile
> @@ -113,12 +113,14 @@ $(TARGET)-syms: prelink.o xen.lds
> $(BASEDIR)/common/symbols-dummy.o
> $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
> $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0
> $(NM) -pa --format=sysv $(@D)/.$(@F).0 \
> - | $(BASEDIR)/tools/symbols --sysv --sort >$(@D)/.$(@F).0.S
> + | $(BASEDIR)/tools/symbols --all-symbols --sysv --sort \
> + >$(@D)/.$(@F).0.S
> $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0.o
> $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
> $(@D)/.$(@F).0.o -o $(@D)/.$(@F).1
> $(NM) -pa --format=sysv $(@D)/.$(@F).1 \
> - | $(BASEDIR)/tools/symbols --sysv --sort --warn-dup
> >$(@D)/.$(@F).1.S
> + | $(BASEDIR)/tools/symbols --all-symbols --sysv --sort
> --warn-dup \
> + >$(@D)/.$(@F).1.S
This addition should be dependent on CONFIG_XSPLICE, not the
least because I expect it to bloat the symbol table quite a bit. And
then - how come this is needed here, but not in the xen.efi rule?
> +uint64_t symbols_lookup_by_name(const char *symname)
I don't think such a function can reasonably return other than void *
or unsigned long.
> +{
> + uint32_t symnum = 0;
> + uint64_t addr = 0, outaddr = 0;
> + int rc;
> + char type;
> + char name[KSYM_NAME_LEN + 1] = {0};
This and likely addr's initializer seem pointless. (And it's questionable
whether you really need both addr and outaddr.)
> + do {
> + rc = xensyms_read(&symnum, &type, &addr, name);
> + if ( rc )
> + break;
> +
> + if ( !strcmp(name, symname) )
> + {
> + outaddr = addr;
> + break;
> + }
> + } while ( name[0] != '\0' );
> +
> + return outaddr;
> +}
Huh - a brute force linear lookup. We've got some 7,000 symbols
right now, and I think we can't expect that to go down.
> +uint64_t xsplice_symbols_lookup_by_name(const char *symname)
> +{
> + struct payload *data;
> + unsigned int i;
> + uint64_t value = 0;
> +
> + spin_lock_recursive(&payload_lock);
> +
> + list_for_each_entry ( data, &payload_list, list )
> + {
> + for ( i = 0; i < data->nsyms; i++ )
> + {
> + if ( !data->symtab[i].new_symbol )
> + continue;
> +
> + if ( !strcmp(data->symtab[i].name, symname) )
> + {
> + value = data->symtab[i].value;
> + goto out;
> + }
> + }
> + }
> +
> +out:
Label indentation.
> @@ -397,8 +429,126 @@ static int prepare_payload(struct payload *payload,
> for ( j = 0; j < 24; j++ )
> if ( f->pad[j] )
> return -EINVAL;
> +
> + /* Lookup function's old address if not already resolved. */
> + if ( !f->old_addr )
> + {
> + f->old_addr = symbols_lookup_by_name(f->name);
> + if ( !f->old_addr )
> + {
> + f->old_addr = xsplice_symbols_lookup_by_name(f->name);
This returns with the lock not held - can you really rely on the symbol
staying around?
> + if ( !f->old_addr )
> + {
> + printk(XENLOG_ERR "%s%s: Could not resolve old address
> of %s\n",
> + XSPLICE, elf->name, f->name);
Any log messages not rate limited by default need careful
consideration. I don't think this is one which needs to be
XENLOG_ERR, even if the condition is an error one.
> +static bool_t is_core_symbol(const struct xsplice_elf *elf,
> + const struct xsplice_elf_sym *sym)
What does "core" here mean?
> +{
> + 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) );
> +}
How does the symbol type matter? Don't you rather mean to
ignore static symbols? Or maybe even just section ones?
Also - stray blanks and !!.
> +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_core_symbol(elf, elf->sym + i) )
> + {
> + nsyms++;
> + strtab_len += strlen(elf->sym[i].name) + 1;
> + }
> + }
> +
> + symtab = xmalloc_array(struct xsplice_symbol, nsyms);
> + if ( !symtab )
> + return -ENOMEM;
> +
> + strtab = xmalloc_bytes(strtab_len);
xmalloc_array(char, strtab_len);
> + if ( !strtab )
> + {
> + xfree(symtab);
> + return -ENOMEM;
> + }
To limit the number of return paths, could I talk you into doing both
allocations and only then checking both return values?
> + nsyms = 0;
> + strtab_len = 0;
> + for ( i = 1; i < elf->nsym; i++ )
> + {
> + if ( is_core_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. */
> + strtab_len += strlcpy(strtab + strtab_len, elf->sym[i].name,
> + KSYM_NAME_LEN) + 1;
> + nsyms++;
> + }
> + }
> +
> + for ( i = 0; i < nsyms; i++ )
> + {
> + bool_t found = 0;
> +
> + for ( j = 0; j < payload->nfuncs; j++ )
> + {
> + if ( symtab[i].value == payload->funcs[j].new_addr )
> + {
> + found = 1;
> + break;
> + }
> + }
> +
> + if ( !found )
> + {
> + if ( xsplice_symbols_lookup_by_name(symtab[i].name) )
> + {
> + printk(XENLOG_ERR "%s%s: duplicate new symbol: %s\n",
> + XSPLICE, elf->name, symtab[i].name);
> + xfree(symtab);
> + xfree(strtab);
> + return -EEXIST;
> + }
> + symtab[i].new_symbol = 1;
> + dprintk(XENLOG_DEBUG, "%s%s: new symbol %s\n",
> + XSPLICE, elf->name, symtab[i].name);
> + }
> + else
> + {
> + dprintk(XENLOG_DEBUG, "%s%s: overriding symbol %s\n",
> + XSPLICE, elf->name, symtab[i].name);
Since you don't do anything here - how is this an override of some
sort?
> @@ -235,15 +236,27 @@ int xsplice_elf_resolve_symbols(struct xsplice_elf
> *elf)
> break;
>
> case SHN_UNDEF:
> - printk(XENLOG_ERR "%s%s: Unknown symbol: %s\n",
> - XSPLICE, elf->name, elf->sym[i].name);
> - return -ENOENT;
> + elf->sym[i].sym->st_value =
> symbols_lookup_by_name(elf->sym[i].name);
> + if ( !elf->sym[i].sym->st_value )
> + {
> + elf->sym[i].sym->st_value =
> + xsplice_symbols_lookup_by_name(elf->sym[i].name);
> + if ( !elf->sym[i].sym->st_value )
> + {
> + printk(XENLOG_ERR "%s%s: Unknown symbol: %s\n",
> + XSPLICE, elf->name, elf->sym[i].name);
> + return -ENOENT;
> + }
> + }
> + dprintk(XENLOG_DEBUG, "%s%s: Undefined symbol resolved: %s
> => 0x%"PRIx64"\n",
> + XSPLICE, elf->name, elf->sym[i].name,
> + (uint64_t)elf->sym[i].sym->st_value);
> break;
>
> case SHN_ABS:
> dprintk(XENLOG_DEBUG, "%s%s: Absolute symbol: %s =>
> 0x%"PRIx64"\n",
> XSPLICE, elf->name, elf->sym[i].name,
> - elf->sym[i].sym->st_value);
> + (uint64_t)elf->sym[i].sym->st_value);
This change does not seem to belong here.
> --- a/xen/include/xen/xsplice.h
> +++ b/xen/include/xen/xsplice.h
> @@ -33,8 +33,16 @@ struct xsplice_patch_func {
> /* Convenience define for printk. */
> #define XSPLICE "xsplice: "
>
> +struct xsplice_symbol {
> + const char *name;
> + uint64_t value;
> + ssize_t size;
While mentioned in the revision log - why signed?
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |