static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
{
    struct xen_bin_image_table *image_info;
    char *image = dom->kernel_blob;
    char *dest;
    size_t image_size = dom->kernel_size;
    uint32_t start_addr;
    uint32_t load_end_addr;
    uint32_t bss_end_addr;
    uint32_t skip, text_size, bss_size;

    image_info = find_table(dom);
    if ( !image_info )
        return -EINVAL;

    start_addr = image_info->header_addr - ((char *)image_info - image);
    load_end_addr = image_info->load_end_addr ?: start_addr + image_size;
    bss_end_addr = image_info->bss_end_addr ?: load_end_addr;

    /* It's possible that we need to skip the first part of the image */
    skip = image_info->load_addr - start_addr;
    text_size = load_end_addr - image_info->load_addr;
    bss_size = bss_end_addr - load_end_addr;

    xc_dom_printf("%s: calculated sizes\n", __FUNCTION__);
    xc_dom_printf("  skip:      0x%" PRIx32 "\n", skip);
    xc_dom_printf("  text_size: 0x%" PRIx32 "\n", text_size);
    xc_dom_printf("  bss_size:  0x%" PRIx32 "\n", bss_size);

    dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart);
    memcpy(dest, image + skip, text_size);
    memset(dest + text_size, 0, bss_size);

    return 0;
}
예제 #2
0
static int xc_dom_load_bin_kernel(struct xc_dom_image *dom)
{
    struct xen_bin_image_table *image_info;
    char *image = dom->kernel_blob;
    char *dest;
    size_t image_size = dom->kernel_size;
    size_t dest_size;
    uint32_t start_addr;
    uint32_t load_end_addr;
    uint32_t bss_end_addr;
    uint32_t skip, text_size, bss_size;

    image_info = find_table(dom);
    if ( !image_info )
        return -EINVAL;

    start_addr = image_info->header_addr - ((char *)image_info - image);
    load_end_addr = image_info->load_end_addr ?: start_addr + image_size;
    bss_end_addr = image_info->bss_end_addr ?: load_end_addr;

    /* It's possible that we need to skip the first part of the image */
    skip = image_info->load_addr - start_addr;
    text_size = load_end_addr - image_info->load_addr;
    bss_size = bss_end_addr - load_end_addr;

    DOMPRINTF("%s: calculated sizes", __FUNCTION__);
    DOMPRINTF("  skip:      0x%" PRIx32 "", skip);
    DOMPRINTF("  text_size: 0x%" PRIx32 "", text_size);
    DOMPRINTF("  bss_size:  0x%" PRIx32 "", bss_size);

    dest = xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart, &dest_size);
    if ( dest == NULL )
    {
        DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom, dom->kernel_seg.vstart)"
                  " => NULL", __FUNCTION__);
        return -EINVAL;
    }

    if ( dest_size < text_size ||
         dest_size - text_size < bss_size )
    {
        DOMPRINTF("%s: mapped region is too small for image", __FUNCTION__);
        return -EINVAL;
    }

    if ( image_size < skip ||
         image_size - skip < text_size )
    {
        DOMPRINTF("%s: image is too small for declared text size",
                  __FUNCTION__);
        return -EINVAL;
    }

    memcpy(dest, image + skip, text_size);
    memset(dest + text_size, 0, bss_size);

    return 0;
}
예제 #3
0
static elf_errorstatus xc_dom_load_elf_symtab(struct xc_dom_image *dom,
                                  struct elf_binary *elf, bool load)
{
    struct elf_binary syms;
    ELF_HANDLE_DECL(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2;
    xen_vaddr_t symtab, maxaddr;
    elf_ptrval hdr;
    size_t size;
    unsigned h, count, type, i, tables = 0;
    unsigned long *strtab_referenced = NULL;

    if ( elf_swap(elf) )
    {
        DOMPRINTF("%s: non-native byte order, bsd symtab not supported",
                  __FUNCTION__);
        return 0;
    }

    size = elf->bsd_symtab_pend - elf->bsd_symtab_pstart;

    if ( load )
    {
        char *hdr_ptr;
        size_t allow_size;

        if ( !dom->bsd_symtab_start )
            return 0;
        hdr_ptr = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start, &allow_size);
        if ( hdr_ptr == NULL )
        {
            DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom,dom->bsd_symtab_start"
                      " => NULL", __FUNCTION__);
            return -1;
        }
        elf->caller_xdest_base = hdr_ptr;
        elf->caller_xdest_size = allow_size;
        hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
        elf_store_val(elf, unsigned, hdr, size - sizeof(unsigned));
    }
    else
    {
static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
                                  struct elf_binary *elf, int load)
{
    struct elf_binary syms;
    const elf_shdr *shdr, *shdr2;
    xen_vaddr_t symtab, maxaddr;
    char *hdr;
    size_t size;
    int h, count, type, i, tables = 0;

    if ( elf_swap(elf) )
    {
        xc_dom_printf("%s: non-native byte order, bsd symtab not supported\n",
                      __FUNCTION__);
        return 0;
    }

    if ( load )
    {
        if ( !dom->bsd_symtab_start )
            return 0;
        size = dom->kernel_seg.vend - dom->bsd_symtab_start;
        hdr  = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
        *(int *)hdr = size - sizeof(int);
    }
    else
    {
        size = sizeof(int) + elf_size(elf, elf->ehdr) +
            elf_shdr_count(elf) * elf_size(elf, shdr);
        hdr = xc_dom_malloc(dom, size);
        if ( hdr == NULL )
            return 0;
        dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend);
    }

    memcpy(hdr + sizeof(int),
           elf->image,
           elf_size(elf, elf->ehdr));
    memcpy(hdr + sizeof(int) + elf_size(elf, elf->ehdr),
           elf->image + elf_uval(elf, elf->ehdr, e_shoff),
           elf_shdr_count(elf) * elf_size(elf, shdr));
    if ( elf_64bit(elf) )
    {
        Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int));
        ehdr->e_phoff = 0;
        ehdr->e_phentsize = 0;
        ehdr->e_phnum = 0;
        ehdr->e_shoff = elf_size(elf, elf->ehdr);
        ehdr->e_shstrndx = SHN_UNDEF;
    }
    else
    {
        Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int));
        ehdr->e_phoff = 0;
        ehdr->e_phentsize = 0;
        ehdr->e_phnum = 0;
        ehdr->e_shoff = elf_size(elf, elf->ehdr);
        ehdr->e_shstrndx = SHN_UNDEF;
    }
    if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) )
        return -1;
    if ( xc_dom_logfile )
        elf_set_logfile(&syms, xc_dom_logfile, 1);

    symtab = dom->bsd_symtab_start + sizeof(int);
    maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) +
                           elf_shdr_count(&syms) * elf_size(&syms, shdr));

    xc_dom_printf("%s/%s: bsd_symtab_start=%" PRIx64 ", kernel.end=0x%" PRIx64
                  " -- symtab=0x%" PRIx64 ", maxaddr=0x%" PRIx64 "\n",
                  __FUNCTION__, load ? "load" : "parse",
                  dom->bsd_symtab_start, dom->kernel_seg.vend,
                  symtab, maxaddr);

    count = elf_shdr_count(&syms);
    for ( h = 0; h < count; h++ )
    {
        shdr = elf_shdr_by_index(&syms, h);
        type = elf_uval(&syms, shdr, sh_type);
        if ( type == SHT_STRTAB )
        {
            /* Look for a strtab @i linked to symtab @h. */
            for ( i = 0; i < count; i++ )
            {
                shdr2 = elf_shdr_by_index(&syms, i);
                if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) &&
                     (elf_uval(&syms, shdr2, sh_link) == h) )
                    break;
            }
            /* Skip symtab @h if we found no corresponding strtab @i. */
            if ( i == count )
            {
                if ( elf_64bit(&syms) )
                    *(Elf64_Off*)(&shdr->e64.sh_offset) = 0;
                else
                    *(Elf32_Off*)(&shdr->e32.sh_offset) = 0;
                continue;
            }
        }

        if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
        {
            /* Mangled to be based on ELF header location. */
            if ( elf_64bit(&syms) )
                *(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab;
            else
                *(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab;
            size = elf_uval(&syms, shdr, sh_size);
            maxaddr = elf_round_up(&syms, maxaddr + size);
            tables++;
            xc_dom_printf("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "\n",
                          __FUNCTION__, h,
                          type == SHT_SYMTAB ? "symtab" : "strtab",
                          size, maxaddr);

            if ( load )
            {
                shdr2 = elf_shdr_by_index(elf, h);
                memcpy((void*)elf_section_start(&syms, shdr),
                       elf_section_start(elf, shdr2),
                       size);
            }
        }

        /* Name is NULL. */
        if ( elf_64bit(&syms) )
            *(Elf64_Half*)(&shdr->e64.sh_name) = 0;
        else
            *(Elf32_Word*)(&shdr->e32.sh_name) = 0;
    }

    if ( tables == 0 )
    {
        xc_dom_printf("%s: no symbol table present\n", __FUNCTION__);
        dom->bsd_symtab_start = 0;
        return 0;
    }
    if ( !load )
        dom->kernel_seg.vend = maxaddr;
    return 0;
}