[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.