ia64/xen-unstable

changeset 15688:88bb0d305308

[ELF] Load elf symbols when BSD_SYMTAB=yes.

When a guest kernel specifies BSD_SYMTAB=yes, then Xen loads the ELF
symbols for it. This works with Xen 3.0.4, but not with Xen 3.1.
During the libelf work between Xen 3.0.4 and Xen 3.1 the loading got
broken in the way, that BSD_SYMTAB gets parsed but not handled.

Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
author kfraser@localhost.localdomain
date Wed Aug 01 15:47:54 2007 +0100 (2007-08-01)
parents 0c79a9414f8d
children d83c9d87ede4 f343d3c16dcc 04fb85a46dc5
files xen/arch/x86/domain_build.c xen/common/libelf/libelf-dominfo.c xen/common/libelf/libelf-loader.c xen/common/libelf/libelf-tools.c xen/include/public/libelf.h
line diff
     1.1 --- a/xen/arch/x86/domain_build.c	Wed Aug 01 12:55:10 2007 +0100
     1.2 +++ b/xen/arch/x86/domain_build.c	Wed Aug 01 15:47:54 2007 +0100
     1.3 @@ -316,6 +316,9 @@ int __init construct_dom0(
     1.4             parms.pae       ? ", PAE"  : "",
     1.5             elf_msb(&elf)   ? "msb"    : "lsb",
     1.6             elf.pstart, elf.pend);
     1.7 +    if ( parms.bsd_symtab )
     1.8 +        printk(" Dom0 symbol map 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
     1.9 +               elf.sstart, elf.send);
    1.10  
    1.11      if ( !compatible )
    1.12      {
    1.13 @@ -385,7 +388,7 @@ int __init construct_dom0(
    1.14      v_start          = parms.virt_base;
    1.15      vkern_start      = parms.virt_kstart;
    1.16      vkern_end        = parms.virt_kend;
    1.17 -    vinitrd_start    = round_pgup(vkern_end);
    1.18 +    vinitrd_start    = round_pgup(parms.virt_end);
    1.19      vinitrd_end      = vinitrd_start + initrd_len;
    1.20      vphysmap_start   = round_pgup(vinitrd_end);
    1.21      vphysmap_end     = vphysmap_start + (nr_pages * (!is_pv_32on64_domain(d) ?
    1.22 @@ -795,7 +798,7 @@ int __init construct_dom0(
    1.23  
    1.24      /* Copy the OS image and free temporary buffer. */
    1.25      elf.dest = (void*)vkern_start;
    1.26 -    elf_load_binary(&elf);
    1.27 +    elf_xen_dom_load_binary(&elf, &parms);
    1.28  
    1.29      if ( UNSET_ADDR != parms.virt_hypercall )
    1.30      {
     2.1 --- a/xen/common/libelf/libelf-dominfo.c	Wed Aug 01 12:55:10 2007 +0100
     2.2 +++ b/xen/common/libelf/libelf-dominfo.c	Wed Aug 01 15:47:54 2007 +0100
     2.3 @@ -333,6 +333,99 @@ static int elf_xen_note_check(struct elf
     2.4      return 0;
     2.5  }
     2.6  
     2.7 +
     2.8 +static void elf_xen_loadsymtab(struct elf_binary *elf,
     2.9 +                               struct elf_dom_parms *parms)
    2.10 +{
    2.11 +    unsigned long maxva, len;
    2.12 +
    2.13 +    if ( !parms->bsd_symtab )
    2.14 +        return;
    2.15 +
    2.16 +    /* Calculate the required additional kernel space for the elf image */
    2.17 +
    2.18 +    /* The absolute base address of the elf image */
    2.19 +    maxva = elf_round_up(elf, parms->virt_kend);
    2.20 +    maxva += sizeof(long); /* Space to store the size of the elf image */
    2.21 +    /* Space for the elf and elf section headers */
    2.22 +    maxva += (elf_uval(elf, elf->ehdr, e_ehsize) +
    2.23 +              elf_shdr_count(elf) * elf_uval(elf, elf->ehdr, e_shentsize));
    2.24 +    maxva = elf_round_up(elf, maxva);
    2.25 +
    2.26 +    /* Space for the symbol and string tabs */
    2.27 +    len = (unsigned long)elf->send - (unsigned long)elf->sstart;
    2.28 +    maxva = elf_round_up(elf, maxva + len);
    2.29 +
    2.30 +    /* The address the kernel must expanded to */
    2.31 +    parms->virt_end = maxva;
    2.32 +}
    2.33 +
    2.34 +int elf_xen_dom_load_binary(struct elf_binary *elf,
    2.35 +                            struct elf_dom_parms *parms)
    2.36 +{
    2.37 +    elf_ehdr *sym_ehdr;
    2.38 +    unsigned long shdr, symtab_addr;
    2.39 +    unsigned long maxva, symbase;
    2.40 +    uint8_t i;
    2.41 +    char *p;
    2.42 +
    2.43 +    elf_load_binary(elf);
    2.44 +
    2.45 +    if ( !parms->bsd_symtab )
    2.46 +        return 0;
    2.47 +
    2.48 +#define elf_hdr_elm(_elf, _hdr, _elm, _val)     \
    2.49 +do {                                            \
    2.50 +    if ( elf_64bit(_elf) )                      \
    2.51 +        (_hdr)->e64._elm = _val;                \
    2.52 +    else                                        \
    2.53 +        (_hdr)->e32._elm = _val;                \
    2.54 +} while ( 0 )
    2.55 +
    2.56 +    /* ehdr right after the kernel image (4 byte aligned) */
    2.57 +    symbase = elf_round_up(elf, parms->virt_kend);
    2.58 +    symtab_addr = maxva = symbase + sizeof(long);
    2.59 +
    2.60 +    /* Set up Elf header. */
    2.61 +    sym_ehdr = (elf_ehdr *)symtab_addr;
    2.62 +    maxva = elf_copy_ehdr(elf, sym_ehdr);
    2.63 +
    2.64 +    elf_hdr_elm(elf, sym_ehdr, e_phoff, 0);
    2.65 +    elf_hdr_elm(elf, sym_ehdr, e_shoff, elf_uval(elf, elf->ehdr, e_ehsize));
    2.66 +    elf_hdr_elm(elf, sym_ehdr, e_phentsize, 0);
    2.67 +    elf_hdr_elm(elf, sym_ehdr, e_phnum, 0);
    2.68 +
    2.69 +    /* Copy Elf section headers. */
    2.70 +    shdr = maxva;
    2.71 +    maxva = elf_copy_shdr(elf, (elf_shdr *)shdr);
    2.72 +
    2.73 +    for ( i = 0; i < elf_shdr_count(elf); i++ )
    2.74 +    {
    2.75 +        uint8_t type;
    2.76 +        unsigned long tmp;
    2.77 +        type = elf_uval(elf, (elf_shdr *)shdr, sh_type);
    2.78 +        if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
    2.79 +        {
    2.80 +             elf_msg(elf, "%s: shdr %i at 0x%p -> 0x%p\n", __func__, i,
    2.81 +                     elf_section_start(elf, (elf_shdr *)shdr), (void *)maxva);
    2.82 +             tmp = elf_copy_section(elf, (elf_shdr *)shdr, (void *)maxva);
    2.83 +             /* Mangled to be based on ELF header location. */
    2.84 +             elf_hdr_elm(elf, (elf_shdr *)shdr, sh_offset,
    2.85 +                         maxva - symtab_addr);
    2.86 +             maxva = tmp;
    2.87 +        }
    2.88 +        shdr += elf_uval(elf, elf->ehdr, e_shentsize);
    2.89 +    }
    2.90 +
    2.91 +    /* Write down the actual sym size. */
    2.92 +    p = (char *)symbase;
    2.93 +    *(long *)p = maxva - symtab_addr; /* sym size */
    2.94 +
    2.95 +#undef elf_ehdr_elm
    2.96 +
    2.97 +    return 0;
    2.98 +}
    2.99 +
   2.100  static int elf_xen_addr_calc_check(struct elf_binary *elf,
   2.101                                     struct elf_dom_parms *parms)
   2.102  {
   2.103 @@ -374,22 +467,28 @@ static int elf_xen_addr_calc_check(struc
   2.104      parms->virt_offset = parms->virt_base - parms->elf_paddr_offset;
   2.105      parms->virt_kstart = elf->pstart + parms->virt_offset;
   2.106      parms->virt_kend   = elf->pend   + parms->virt_offset;
   2.107 +    parms->virt_end    = parms->virt_kend;
   2.108  
   2.109      if ( parms->virt_entry == UNSET_ADDR )
   2.110          parms->virt_entry = elf_uval(elf, elf->ehdr, e_entry);
   2.111  
   2.112 +    if ( parms->bsd_symtab )
   2.113 +        elf_xen_loadsymtab(elf, parms);
   2.114 +
   2.115      elf_msg(elf, "%s: addresses:\n", __FUNCTION__);
   2.116      elf_msg(elf, "    virt_base        = 0x%" PRIx64 "\n", parms->virt_base);
   2.117      elf_msg(elf, "    elf_paddr_offset = 0x%" PRIx64 "\n", parms->elf_paddr_offset);
   2.118      elf_msg(elf, "    virt_offset      = 0x%" PRIx64 "\n", parms->virt_offset);
   2.119      elf_msg(elf, "    virt_kstart      = 0x%" PRIx64 "\n", parms->virt_kstart);
   2.120      elf_msg(elf, "    virt_kend        = 0x%" PRIx64 "\n", parms->virt_kend);
   2.121 +    elf_msg(elf, "    virt_end         = 0x%" PRIx64 "\n", parms->virt_end);
   2.122      elf_msg(elf, "    virt_entry       = 0x%" PRIx64 "\n", parms->virt_entry);
   2.123  
   2.124      if ( (parms->virt_kstart > parms->virt_kend) ||
   2.125           (parms->virt_entry < parms->virt_kstart) ||
   2.126           (parms->virt_entry > parms->virt_kend) ||
   2.127 -         (parms->virt_base > parms->virt_kstart) )
   2.128 +         (parms->virt_base > parms->virt_kstart) ||
   2.129 +         (parms->virt_kend > parms->virt_end) )
   2.130      {
   2.131          elf_err(elf, "%s: ERROR: ELF start or entries are out of bounds.\n",
   2.132                  __FUNCTION__);
     3.1 --- a/xen/common/libelf/libelf-loader.c	Wed Aug 01 12:55:10 2007 +0100
     3.2 +++ b/xen/common/libelf/libelf-loader.c	Wed Aug 01 15:47:54 2007 +0100
     3.3 @@ -10,6 +10,8 @@ int elf_init(struct elf_binary *elf, con
     3.4  {
     3.5      const elf_shdr *shdr;
     3.6      uint64_t i, count, section, offset;
     3.7 +    uint64_t low = -1;
     3.8 +    uint64_t high = 0;
     3.9  
    3.10      if ( !elf_is_elfbinary(image) )
    3.11      {
    3.12 @@ -24,7 +26,11 @@ int elf_init(struct elf_binary *elf, con
    3.13      elf->class = elf->ehdr->e32.e_ident[EI_CLASS];
    3.14      elf->data = elf->ehdr->e32.e_ident[EI_DATA];
    3.15  
    3.16 -    /* sanity check phdr */
    3.17 +#ifdef VERBOSE
    3.18 +    elf_set_verbose(elf);
    3.19 +#endif
    3.20 +
    3.21 +    /* Sanity check phdr. */
    3.22      offset = elf_uval(elf, elf->ehdr, e_phoff) +
    3.23          elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf);
    3.24      if ( offset > elf->size )
    3.25 @@ -34,7 +40,7 @@ int elf_init(struct elf_binary *elf, con
    3.26          return -1;
    3.27      }
    3.28  
    3.29 -    /* sanity check shdr */
    3.30 +    /* Sanity check shdr. */
    3.31      offset = elf_uval(elf, elf->ehdr, e_shoff) +
    3.32          elf_uval(elf, elf->ehdr, e_shentsize) * elf_shdr_count(elf);
    3.33      if ( offset > elf->size )
    3.34 @@ -44,29 +50,55 @@ int elf_init(struct elf_binary *elf, con
    3.35          return -1;
    3.36      }
    3.37  
    3.38 -    /* find section string table */
    3.39 +    /* Find section string table. */
    3.40      section = elf_uval(elf, elf->ehdr, e_shstrndx);
    3.41      shdr = elf_shdr_by_index(elf, section);
    3.42      if ( shdr != NULL )
    3.43          elf->sec_strtab = elf_section_start(elf, shdr);
    3.44  
    3.45 -    /* find symbol table, symbol string table */
    3.46 +    /* Find symbol table and symbol string table. */
    3.47      count = elf_shdr_count(elf);
    3.48      for ( i = 0; i < count; i++ )
    3.49      {
    3.50 +        const char *sh_symend, *sh_strend;
    3.51 +
    3.52          shdr = elf_shdr_by_index(elf, i);
    3.53          if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB )
    3.54              continue;
    3.55          elf->sym_tab = shdr;
    3.56 +        sh_symend = (const char *)elf_section_end(elf, shdr);
    3.57          shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link));
    3.58          if ( shdr == NULL )
    3.59          {
    3.60              elf->sym_tab = NULL;
    3.61 +            sh_symend = 0;
    3.62              continue;
    3.63          }
    3.64          elf->sym_strtab = elf_section_start(elf, shdr);
    3.65 -        break;
    3.66 +        sh_strend = (const char *)elf_section_end(elf, shdr);
    3.67 +
    3.68 +        if ( low > (unsigned long)elf->sym_tab )
    3.69 +            low = (unsigned long)elf->sym_tab;
    3.70 +        if ( low > (unsigned long)shdr )
    3.71 +            low = (unsigned long)shdr;
    3.72 +
    3.73 +        if ( high < ((unsigned long)sh_symend) )
    3.74 +            high = (unsigned long)sh_symend;
    3.75 +        if ( high < ((unsigned long)sh_strend) )
    3.76 +            high = (unsigned long)sh_strend;
    3.77 +
    3.78 +        elf_msg(elf, "%s: shdr: sym_tab=%p size=0x%" PRIx64 "\n",
    3.79 +                __FUNCTION__, elf->sym_tab,
    3.80 +                elf_uval(elf, elf->sym_tab, sh_size));
    3.81 +        elf_msg(elf, "%s: shdr: str_tab=%p size=0x%" PRIx64 "\n",
    3.82 +                __FUNCTION__, elf->sym_strtab, elf_uval(elf, shdr, sh_size));
    3.83 +
    3.84 +        elf->sstart = low;
    3.85 +        elf->send = high;
    3.86 +        elf_msg(elf, "%s: symbol map: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
    3.87 +                __FUNCTION__, elf->sstart, elf->send);
    3.88      }
    3.89 +
    3.90      return 0;
    3.91  }
    3.92  
     4.1 --- a/xen/common/libelf/libelf-tools.c	Wed Aug 01 12:55:10 2007 +0100
     4.2 +++ b/xen/common/libelf/libelf-tools.c	Wed Aug 01 15:47:54 2007 +0100
     4.3 @@ -238,6 +238,36 @@ int elf_phdr_is_loadable(struct elf_bina
     4.4      return ((p_type == PT_LOAD) && (p_flags & (PF_W | PF_X)) != 0);
     4.5  }
     4.6  
     4.7 +unsigned long
     4.8 +elf_copy_ehdr(struct elf_binary *elf, void *dest)
     4.9 +{
    4.10 +    uint64_t size;
    4.11 +
    4.12 +    size = elf_uval(elf, elf->ehdr, e_ehsize);
    4.13 +    memcpy(dest, elf->ehdr, size);
    4.14 +    return elf_round_up(elf, (unsigned long)(dest) + size);
    4.15 +}
    4.16 +
    4.17 +unsigned long
    4.18 +elf_copy_shdr(struct elf_binary *elf, void *dest)
    4.19 +{
    4.20 +    uint64_t size;
    4.21 +
    4.22 +    size = elf_shdr_count(elf) * elf_uval(elf, elf->ehdr, e_shentsize);
    4.23 +    memcpy(dest, elf->image + elf_uval(elf, elf->ehdr, e_shoff), size);
    4.24 +    return elf_round_up(elf, (unsigned long)(dest) + size);
    4.25 +}
    4.26 +
    4.27 +unsigned long
    4.28 +elf_copy_section(struct elf_binary *elf, const elf_shdr *shdr, void *dest)
    4.29 +{
    4.30 +    uint64_t size;
    4.31 +
    4.32 +    size = elf_uval(elf, shdr, sh_size);
    4.33 +    memcpy(dest, elf_section_start(elf, shdr), size);
    4.34 +    return elf_round_up(elf, (unsigned long)(dest) + size);
    4.35 +}
    4.36 +
    4.37  /*
    4.38   * Local variables:
    4.39   * mode: C
     5.1 --- a/xen/include/public/libelf.h	Wed Aug 01 12:55:10 2007 +0100
     5.2 +++ b/xen/include/public/libelf.h	Wed Aug 01 15:47:54 2007 +0100
     5.3 @@ -65,6 +65,8 @@ struct elf_binary {
     5.4  
     5.5      /* loaded to */
     5.6      char *dest;
     5.7 +    uint64_t sstart;
     5.8 +    uint64_t send;
     5.9      uint64_t pstart;
    5.10      uint64_t pend;
    5.11      uint64_t reloc_offset;
    5.12 @@ -91,33 +93,32 @@ struct elf_binary {
    5.13  #define elf_lsb(elf)   (ELFDATA2LSB == (elf)->data)
    5.14  #define elf_swap(elf)  (NATIVE_ELFDATA != (elf)->data)
    5.15  
    5.16 -#define elf_uval(elf, str, elem)			\
    5.17 -	((ELFCLASS64 == (elf)->class)			\
    5.18 -	? elf_access_unsigned((elf), (str),		\
    5.19 -		offsetof(typeof(*(str)),e64.elem),	\
    5.20 -		sizeof((str)->e64.elem))		\
    5.21 -	: elf_access_unsigned((elf), (str),		\
    5.22 -		offsetof(typeof(*(str)),e32.elem),	\
    5.23 -		sizeof((str)->e32.elem)))
    5.24 +#define elf_uval(elf, str, elem)                                        \
    5.25 +    ((ELFCLASS64 == (elf)->class)                                       \
    5.26 +     ? elf_access_unsigned((elf), (str),                                \
    5.27 +                           offsetof(typeof(*(str)),e64.elem),           \
    5.28 +                           sizeof((str)->e64.elem))                     \
    5.29 +     : elf_access_unsigned((elf), (str),                                \
    5.30 +                           offsetof(typeof(*(str)),e32.elem),           \
    5.31 +                           sizeof((str)->e32.elem)))
    5.32  
    5.33 -#define elf_sval(elf, str, elem)			\
    5.34 -	((ELFCLASS64 == (elf)->class)			\
    5.35 -	? elf_access_signed((elf), (str),		\
    5.36 -		offsetof(typeof(*(str)),e64.elem),	\
    5.37 -		sizeof((str)->e64.elem))		\
    5.38 -	: elf_access_signed((elf), (str),		\
    5.39 -		offsetof(typeof(*(str)),e32.elem),	\
    5.40 -		sizeof((str)->e32.elem)))
    5.41 +#define elf_sval(elf, str, elem)                                        \
    5.42 +    ((ELFCLASS64 == (elf)->class)                                       \
    5.43 +     ? elf_access_signed((elf), (str),                                  \
    5.44 +                         offsetof(typeof(*(str)),e64.elem),             \
    5.45 +                         sizeof((str)->e64.elem))                       \
    5.46 +     : elf_access_signed((elf), (str),                                  \
    5.47 +                         offsetof(typeof(*(str)),e32.elem),             \
    5.48 +                         sizeof((str)->e32.elem)))
    5.49  
    5.50 -#define elf_size(elf, str)		\
    5.51 -	((ELFCLASS64 == (elf)->class)	\
    5.52 -	? sizeof((str)->e64)		\
    5.53 -	: sizeof((str)->e32))
    5.54 +#define elf_size(elf, str)                              \
    5.55 +    ((ELFCLASS64 == (elf)->class)                       \
    5.56 +     ? sizeof((str)->e64) : sizeof((str)->e32))
    5.57  
    5.58  uint64_t elf_access_unsigned(struct elf_binary *elf, const void *ptr,
    5.59 -			     uint64_t offset, size_t size);
    5.60 +                             uint64_t offset, size_t size);
    5.61  int64_t elf_access_signed(struct elf_binary *elf, const void *ptr,
    5.62 -			  uint64_t offset, size_t size);
    5.63 +                          uint64_t offset, size_t size);
    5.64  
    5.65  uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr);
    5.66  
    5.67 @@ -149,6 +150,11 @@ const elf_note *elf_note_next(struct elf
    5.68  int elf_is_elfbinary(const void *image);
    5.69  int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr);
    5.70  
    5.71 +unsigned long elf_copy_ehdr(struct elf_binary *elf, void *dest);
    5.72 +unsigned long elf_copy_shdr(struct elf_binary *elf, void *dest);
    5.73 +unsigned long elf_copy_section(struct elf_binary *elf,
    5.74 +                               const elf_shdr *shdr, void *dest);
    5.75 +
    5.76  /* ------------------------------------------------------------------------ */
    5.77  /* xc_libelf_loader.c                                                       */
    5.78  
    5.79 @@ -185,8 +191,8 @@ struct xen_elfnote {
    5.80      enum xen_elfnote_type type;
    5.81      const char *name;
    5.82      union {
    5.83 -	const char *str;
    5.84 -	uint64_t num;
    5.85 +        const char *str;
    5.86 +        uint64_t num;
    5.87      } data;
    5.88  };
    5.89  
    5.90 @@ -215,7 +221,8 @@ struct elf_dom_parms {
    5.91      /* calculated */
    5.92      uint64_t virt_offset;
    5.93      uint64_t virt_kstart;
    5.94 -    uint64_t virt_kend;
    5.95 +    uint64_t virt_kend; /* end of kernel image */
    5.96 +    uint64_t virt_end;  /* end of kernel symtab (== virt_kend if none) */
    5.97  };
    5.98  
    5.99  static inline void elf_xen_feature_set(int nr, uint32_t * addr)
   5.100 @@ -228,14 +235,17 @@ static inline int elf_xen_feature_get(in
   5.101  }
   5.102  
   5.103  int elf_xen_parse_features(const char *features,
   5.104 -			   uint32_t *supported,
   5.105 -			   uint32_t *required);
   5.106 +                           uint32_t *supported,
   5.107 +                           uint32_t *required);
   5.108  int elf_xen_parse_note(struct elf_binary *elf,
   5.109 -		       struct elf_dom_parms *parms,
   5.110 -		       const elf_note *note);
   5.111 +                       struct elf_dom_parms *parms,
   5.112 +                       const elf_note *note);
   5.113  int elf_xen_parse_guest_info(struct elf_binary *elf,
   5.114 -			     struct elf_dom_parms *parms);
   5.115 +                             struct elf_dom_parms *parms);
   5.116  int elf_xen_parse(struct elf_binary *elf,
   5.117 -		  struct elf_dom_parms *parms);
   5.118 +                  struct elf_dom_parms *parms);
   5.119 +
   5.120 +int elf_xen_dom_load_binary(struct elf_binary *elf,
   5.121 +                            struct elf_dom_parms *parms);
   5.122  
   5.123  #endif /* __XC_LIBELF__ */