[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v1 10/11] xsplice: Add support for exception tables



On Tue, Nov 03, 2015 at 06:16:07PM +0000, Ross Lagerwall wrote:
> Add support for exception tables contained within xsplice modules. If an
> exception occurs search either the main exception table or a particular
> active module's exception table depending on the instruction pointer.

s/module/payload/
> 
> Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
> ---
>  xen/arch/x86/extable.c        | 36 ++++++++++++++++++++++--------------
>  xen/common/xsplice.c          | 41 +++++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-x86/uaccess.h |  5 +++++
>  xen/include/xen/xsplice.h     |  2 ++
>  4 files changed, 70 insertions(+), 14 deletions(-)
> 
> diff --git a/xen/arch/x86/extable.c b/xen/arch/x86/extable.c
> index 89b5bcb..2787a92 100644
> --- a/xen/arch/x86/extable.c
> +++ b/xen/arch/x86/extable.c
> @@ -4,6 +4,7 @@
>  #include <xen/perfc.h>
>  #include <xen/sort.h>
>  #include <xen/spinlock.h>
> +#include <xen/xsplice.h>
>  #include <asm/uaccess.h>
>  
>  #define EX_FIELD(ptr, field) ((unsigned long)&(ptr)->field + (ptr)->field)
> @@ -18,7 +19,7 @@ static inline unsigned long ex_cont(const struct 
> exception_table_entry *x)
>       return EX_FIELD(x, cont);
>  }
>  
> -static int __init cmp_ex(const void *a, const void *b)
> +static int cmp_ex(const void *a, const void *b)
>  {
>       const struct exception_table_entry *l = a, *r = b;
>       unsigned long lip = ex_addr(l);
> @@ -33,7 +34,7 @@ static int __init cmp_ex(const void *a, const void *b)
>  }
>  
>  #ifndef swap_ex
> -static void __init swap_ex(void *a, void *b, int size)
> +static void swap_ex(void *a, void *b, int size)
>  {
>       struct exception_table_entry *l = a, *r = b, tmp;
>       long delta = b - a;
> @@ -46,19 +47,23 @@ static void __init swap_ex(void *a, void *b, int size)
>  }
>  #endif
>  
> -void __init sort_exception_tables(void)
> +void sort_exception_table(struct exception_table_entry *start,
> +                          struct exception_table_entry *stop)
>  {
> -    sort(__start___ex_table, __stop___ex_table - __start___ex_table,
> -         sizeof(struct exception_table_entry), cmp_ex, swap_ex);
> -    sort(__start___pre_ex_table,
> -         __stop___pre_ex_table - __start___pre_ex_table,
> +    sort(start, stop - start,
>           sizeof(struct exception_table_entry), cmp_ex, swap_ex);
>  }
>  
> -static inline unsigned long
> -search_one_table(const struct exception_table_entry *first,
> -                 const struct exception_table_entry *last,
> -                 unsigned long value)
> +void __init sort_exception_tables(void)
> +{
> +    sort_exception_table(__start___ex_table, __stop___ex_table);
> +    sort_exception_table(__start___pre_ex_table, __stop___pre_ex_table);
> +}
> +
> +unsigned long
> +search_one_extable(const struct exception_table_entry *first,
> +                   const struct exception_table_entry *last,
> +                   unsigned long value)
>  {
>      const struct exception_table_entry *mid;
>      long diff;
> @@ -80,15 +85,18 @@ search_one_table(const struct exception_table_entry 
> *first,
>  unsigned long
>  search_exception_table(unsigned long addr)
>  {
> -    return search_one_table(
> -        __start___ex_table, __stop___ex_table-1, addr);
> +    if ( likely(is_kernel(addr)) )
> +        return search_one_extable(
> +            __start___ex_table, __stop___ex_table-1, addr);
> +    else
> +        return search_module_extables(addr);
>  }
>  
>  unsigned long
>  search_pre_exception_table(struct cpu_user_regs *regs)
>  {
>      unsigned long addr = (unsigned long)regs->eip;
> -    unsigned long fixup = search_one_table(
> +    unsigned long fixup = search_one_extable(
>          __start___pre_ex_table, __stop___pre_ex_table-1, addr);
>      if ( fixup )
>      {
> diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c
> index 982954b..c5a403b 100644
> --- a/xen/common/xsplice.c
> +++ b/xen/common/xsplice.c
> @@ -45,6 +45,10 @@ struct payload {
>  
>      struct bug_frame *start_bug_frames[4];
>      struct bug_frame *stop_bug_frames[4];
> +#ifdef CONFIG_X86
> +    struct exception_table_entry *start_ex_table;
> +    struct exception_table_entry *stop_ex_table;
> +#endif
>  
>      char  id[XEN_XSPLICE_NAME_SIZE + 1];          /* Name of it. */
>  };
> @@ -691,6 +695,17 @@ static int find_special_sections(struct payload *payload,
>          payload->stop_bug_frames[i] = (struct bug_frame *)(sec->load_addr + 
> sec->sec->sh_size);
>      }
>  
> +#ifdef CONFIG_X86
> +    sec = xsplice_elf_sec_by_name(elf, ".ex_table");
> +    if ( sec )
> +    {
> +        payload->start_ex_table = (struct exception_table_entry 
> *)sec->load_addr;
> +        payload->stop_ex_table = (struct exception_table_entry 
> *)(sec->load_addr + sec->sec->sh_size);

Please double-check that sh_size is not some funny value. For example it
may be 0, or worst - not aligned to the size of 'struct
exception_table_entry'!

> +
> +        sort_exception_table(payload->start_ex_table, 
> payload->stop_ex_table);
> +    }
> +#endif
> +
>      return 0;
>  }
>  
> @@ -999,6 +1014,32 @@ bool_t is_active_module_text(unsigned long addr)
>      return false;
>  }
>  
> +#ifdef CONFIG_X86
> +unsigned long search_module_extables(unsigned long addr)
> +{
> +    struct payload *data;
> +    unsigned long ret;
> +
> +    /* No locking since this list is only ever changed during apply or revert
> +     * context. */
> +    list_for_each_entry ( data, &applied_list, applied_list )
> +    {
> +        if ( !data->start_ex_table )
> +            continue;
> +        if ( !((void *)addr >= data->module_address &&
> +               (void *)addr < (data->module_address + data->core_text_size)))

The last ')' needs to have space before it.

> +            continue;
> +
> +        ret = search_one_extable(data->start_ex_table, data->stop_ex_table - 
> 1,
> +                                 addr);
> +        if ( ret )
> +            return ret;
> +    }
> +
> +    return 0;
> +}
> +#endif
> +
>  static int __init xsplice_init(void)
>  {
>      register_keyhandler('x', xsplice_printall, "print xsplicing info", 1);
> diff --git a/xen/include/asm-x86/uaccess.h b/xen/include/asm-x86/uaccess.h
> index 947470d..9e67bf0 100644
> --- a/xen/include/asm-x86/uaccess.h
> +++ b/xen/include/asm-x86/uaccess.h
> @@ -276,6 +276,11 @@ extern struct exception_table_entry 
> __start___pre_ex_table[];
>  extern struct exception_table_entry __stop___pre_ex_table[];
>  
>  extern unsigned long search_exception_table(unsigned long);
> +extern unsigned long search_one_extable(const struct exception_table_entry 
> *first,
> +                                        const struct exception_table_entry 
> *last,
> +                                        unsigned long value);
>  extern void sort_exception_tables(void);
> +extern void sort_exception_table(struct exception_table_entry *start,
> +                                 struct exception_table_entry *stop);
>  
>  #endif /* __X86_UACCESS_H__ */
> diff --git a/xen/include/xen/xsplice.h b/xen/include/xen/xsplice.h
> index 772fa3a..485eb08 100644
> --- a/xen/include/xen/xsplice.h
> +++ b/xen/include/xen/xsplice.h
> @@ -26,6 +26,8 @@ struct bug_frame * xsplice_find_bug(const char *eip, int 
> *id);
>  bool_t is_module(const void *addr);
>  bool_t is_active_module_text(unsigned long addr);
>  
> +unsigned long search_module_extables(unsigned long addr);
> +
>  /* Arch hooks */
>  int xsplice_verify_elf(uint8_t *data, ssize_t len);
>  int xsplice_perform_rel(struct xsplice_elf *elf,
> -- 
> 2.4.3
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel

_______________________________________________
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®.