コード例 #1
0
ファイル: x86boot.c プロジェクト: achreto/barrelfish
static errval_t relocate_cpu_binary(lvaddr_t cpu_binary,
                                    struct Elf64_Ehdr *cpu_head,
                                    struct elf_allocate_state state,
                                    struct frame_identity frameid,
                                    genpaddr_t arch_page_size)
{
    switch (cpu_head->e_machine) {
    case EM_X86_64:
    case EM_K1OM: {
        struct Elf64_Shdr *rela, *symtab, *symhead =
            (struct Elf64_Shdr *)(cpu_binary + (uintptr_t)cpu_head->e_shoff);

        assert(cpu_head->e_shoff != 0);
        rela = elf64_find_section_header_type(symhead, cpu_head->e_shnum, SHT_RELA);
        assert(rela != NULL);
        symtab = elf64_find_section_header_type(symhead, cpu_head->e_shnum, SHT_DYNSYM);
        assert(symtab != NULL);
        elf64_relocate(frameid.base + arch_page_size, state.elfbase,
                       (struct Elf64_Rela *)(uintptr_t)(cpu_binary + rela->sh_offset),
                       rela->sh_size,
                       (struct Elf64_Sym *)(uintptr_t)(cpu_binary + symtab->sh_offset),
                       symtab->sh_size,
                       state.elfbase, state.vbase);
        break;
    }
    case EM_386: {
        struct Elf32_Ehdr *head32 = (struct Elf32_Ehdr *)cpu_binary;

        struct Elf32_Shdr *rel, *symtab, *symhead =
            (struct Elf32_Shdr *)(cpu_binary + (uintptr_t)head32->e_shoff);

        rel = elf32_find_section_header_type(symhead, head32->e_shnum, SHT_REL);
        assert(rel != NULL);
        symtab = elf32_find_section_header_type(symhead, head32->e_shnum,
                                                SHT_DYNSYM);
        assert(symtab != NULL);
        elf32_relocate(frameid.base + arch_page_size, state.elfbase,
                       (struct Elf32_Rel *)(uintptr_t)(cpu_binary + rel->sh_offset),
                       rel->sh_size,
                       (struct Elf32_Sym *)(uintptr_t)(cpu_binary + symtab->sh_offset),
                       symtab->sh_size,
                       state.elfbase, state.vbase);
        break;
    }
    default:
        return SPAWN_ERR_UNKNOWN_TARGET_ARCH;
    }

    return SYS_ERR_OK;
}
コード例 #2
0
ファイル: elf32.c プロジェクト: BarrelfishOS/barrelfish
/**
 * \brief finds the symbol by its address
 *
 * \param elf_base  virtual address where the elf image is mapped
 * \param elf_bytes size of the mapped elf image
 * \param addr      virtual address of the symbol
 * \param index     returns the index of the symbol
 *
 * \returns pointer to the symbol
 *          NULL if there is none
 */
struct Elf32_Sym *
elf32_find_symbol_by_addr(genvaddr_t elf_base, size_t elf_bytes,
                          lvaddr_t addr, uintptr_t *sindex)
{
    struct Elf32_Sym *sym = NULL;
    struct Elf32_Shdr *shead;
    struct Elf32_Shdr *symtab;

    lvaddr_t elfbase = (lvaddr_t)elf_base;
    struct Elf32_Ehdr *head = (struct Elf32_Ehdr *)elfbase;

    // just a sanity check
    if (!IS_ELF(*head) || head->e_ident[EI_CLASS] != ELFCLASS32) {
        return NULL;
    }

    shead = (struct Elf32_Shdr *)(elfbase + (uintptr_t)head->e_shoff);

    symtab = elf32_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);

    uintptr_t symbase = elfbase + (uintptr_t)symtab->sh_offset;

    uintptr_t idx = 0;
    for (uintptr_t i = 0; i < symtab->sh_size; i += sizeof(struct Elf32_Sym)) {
        // getting the symbol
        sym = (struct Elf32_Sym *)(symbase + i);

        /* XXX: not handling relocatable symbols */
        if (sym->st_value == addr) {
            break;
        }

        idx++;
    }

    if (sym != NULL) {
        if (sindex) {
            *sindex = idx;
        }
    }
    return sym;
}
コード例 #3
0
ファイル: elf32.c プロジェクト: BarrelfishOS/barrelfish
const char *
elf32_get_symbolname(struct Elf32_Ehdr *head,
                     struct Elf32_Sym *sym)
{
    struct Elf32_Shdr *shead;
    struct Elf32_Shdr *symtab;

    // just a sanity check
    if (!IS_ELF(*head) || head->e_ident[EI_CLASS] != ELFCLASS64) {
        return NULL;
    }

    uintptr_t elfbase = (uintptr_t)head;

    shead = (struct Elf32_Shdr *)(elfbase + (uintptr_t)head->e_shoff);

    symtab = elf32_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);

    // find the section of the associacted string table
    struct Elf32_Shdr *strtab = shead+symtab->sh_link;

    // get the pointer to the symbol name from string table + string index
    return (const char *)elfbase + strtab->sh_offset + sym->st_name;
}
コード例 #4
0
ファイル: elf32.c プロジェクト: BarrelfishOS/barrelfish
/**
 * \brief Load ELF32 binary image into memory
 *
 * This function loads an ELF32 binary image, based at 'base' and of size
 * 'size' into the memory provided by 'allocate'
 *
 * \param em_machine    ELF machine type.
 * \param allocate      Memory allocation function.
 * \param state         Pointer to state for allocation function.
 * \param base          Base address of ELF32 binary image in memory.
 * \param size          Size of ELF32 binary image in bytes.
 * \param retentry      Used to return entry point address
 * \param ret_tlsbase   Used to return TLS block base address
 * \param ret_tlsinitlen Used to return length of initialised TLS data block
 * \param ret_tlstotallen Used to return total length of TLS data
 */
errval_t elf32_load(uint16_t em_machine, elf_allocator_fn allocate_func,
                    void *state, lvaddr_t base, size_t size,
                    genvaddr_t *retentry,
                    genvaddr_t *ret_tlsbase, size_t *ret_tlsinitlen,
                    size_t *ret_tlstotallen)
{
    struct Elf32_Ehdr *head = (struct Elf32_Ehdr *)base;
    errval_t err;
    int i;

    // Check for valid file size
    if (size < sizeof(struct Elf32_Ehdr)) {
        return ELF_ERR_FILESZ;
    }

    // Stage 1: Check for compatible ELF32 header: check endianess
    if(is_big_endian() && head->e_ident[EI_DATA] != ELFDATA2MSB){
        return ELF_ERR_HEADER;
    } else if(!is_big_endian() && head->e_ident[EI_DATA] != ELFDATA2LSB){
        return ELF_ERR_HEADER;
    }

    // Stage 2: Check for compatible ELF32 header
    if (!IS_ELF(*head)
        || head->e_ident[EI_CLASS] != ELFCLASS32
//        || head->e_ident[EI_DATA] != ELFDATA2MSB   //Enhanced with a function to check machine endianess
        || head->e_ident[EI_VERSION] != EV_CURRENT
        || head->e_ident[EI_OSABI] != ELFOSABI_SYSV
        || head->e_ident[EI_ABIVERSION] != 0
        || (head->e_type != ET_EXEC && head->e_type != ET_DYN)
        || head->e_machine != em_machine
        || head->e_version != EV_CURRENT) {
        return ELF_ERR_HEADER;
    }

    // More sanity checks
    if (head->e_phoff + head->e_phentsize * head->e_phnum > size
        || head->e_phentsize != sizeof(struct Elf32_Phdr)) {
        return ELF_ERR_PROGHDR;
    }

    struct Elf32_Shdr *shead =
        (struct Elf32_Shdr *)(base + (uintptr_t)head->e_shoff);
    struct Elf32_Shdr *rela =
        elf32_find_section_header_type(shead, head->e_shnum, SHT_REL);
    struct Elf32_Shdr *symtab =
        elf32_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);

    size_t rela_size = rela ? rela->sh_size : 0, new_rela_size = 0;
    struct Elf32_Shdr *new_rela = NULL;

    // Find dynamic program header, if any
    struct Elf32_Phdr *phead =
        (struct Elf32_Phdr *)(base + (uintptr_t)head->e_phoff);
    for (i = 0; i < head->e_phnum; i++) {
        struct Elf32_Phdr *p = &phead[i];

        if (p->p_type == PT_DYNAMIC) {
            struct Elf32_Dyn *dynamic = (void *)(base + (uintptr_t)p->p_offset);
            int n_dynamic = p->p_filesz / sizeof(struct Elf32_Dyn);
            for (int j = 0; j < n_dynamic; j++) {
                switch (dynamic[j].d_tag) {
                case DT_RELA:
                    // virtual address of relocations, look for matching section
                    new_rela =
                        elf32_find_section_header_vaddr(shead, head->e_shnum,
                                                        dynamic[j].d_un.d_val);
                    break;

                case DT_RELASZ:
                    // store size of relocations, as they may cover more than
                    // one section
                    new_rela_size = dynamic[j].d_un.d_val;
                    break;

                case DT_SYMTAB:
                    // virtual address of symtab, look for matching section
                    symtab =
                        elf32_find_section_header_vaddr(shead, head->e_shnum,
                                                        dynamic[j].d_un.d_val);
                    break;

                case DT_SYMENT:
                    assert(dynamic[j].d_un.d_val == sizeof(struct Elf32_Sym));
                    break;
                }
            }

            if (new_rela != NULL) {
                assert(new_rela_size != 0);
                rela = new_rela;
                rela_size = new_rela_size;
            }
            break;
        }
    }

    genvaddr_t tls_base = 0;
    size_t tls_init_len = 0, tls_total_len = 0;

    // Process program headers to load file
    for (i = 0; i < head->e_phnum; i++) {
        struct Elf32_Phdr *p = &phead[i];

        if (p->p_type == PT_LOAD) {
            // Map segment in user-space memory
            void *dest = NULL;
            err = allocate_func(state, p->p_vaddr, p->p_memsz, p->p_flags, &dest);
            if (err_is_fail(err)) {
                return err_push(err, ELF_ERR_ALLOCATE);
            }
            assert(dest != NULL);

            // Copy file segment into memory
            memcpy(dest, (void *)(base + (uintptr_t)p->p_offset), p->p_filesz);

            // Initialize rest of memory segment (ie. BSS) with all zeroes
            memset((char *)dest + p->p_filesz, 0, p->p_memsz - p->p_filesz);

            // Apply relocations
            if (rela != NULL && symtab != NULL) {
                elf32_relocate(p->p_vaddr, p->p_vaddr,
                               (struct Elf32_Rel *)
                               (base + (uintptr_t)rela->sh_offset),
                               rela_size,
                               (struct Elf32_Sym *)
                               (base + (uintptr_t)symtab->sh_offset),
                               symtab->sh_size, p->p_vaddr, dest);
            }
        } else if (p->p_type == PT_TLS) {
            assert(p->p_vaddr != 0);
            assert(tls_base == 0); // if not we have multiple TLS sections!
            tls_base = p->p_vaddr;
            tls_init_len = p->p_filesz;
            tls_total_len = p->p_memsz;
        }
    }

    if (retentry != NULL) {
        *retentry = head->e_entry;
    }

    if (ret_tlsbase != NULL) {
        *ret_tlsbase = tls_base;
    }

    if (ret_tlsinitlen != NULL) {
        *ret_tlsinitlen = tls_init_len;
    }

    if (ret_tlstotallen != NULL) {
        *ret_tlstotallen = tls_total_len;
    }

    return SYS_ERR_OK;
}
コード例 #5
0
ファイル: elf32.c プロジェクト: BarrelfishOS/barrelfish
uint32_t
elf32_count_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
                          const char *name, uint8_t contains, uint8_t type,
                          size_t *ret_bytes)
{
    struct Elf32_Sym *sym = NULL;
    struct Elf32_Shdr *shead;
    struct Elf32_Shdr *symtab;
    const char *symname;

    lvaddr_t elfbase = (lvaddr_t)elf_base;
    struct Elf32_Ehdr *head = (struct Elf32_Ehdr *)elfbase;

    // just a sanity check
    if (!IS_ELF(*head) || head->e_ident[EI_CLASS] != ELFCLASS64) {
        return 0;
    }

    uint32_t count = 0;
    size_t bytes = 0;

    shead = (struct Elf32_Shdr *)(elfbase + (uintptr_t)head->e_shoff);

    symtab = elf32_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);

    uintptr_t symbase = elfbase + (uintptr_t)symtab->sh_offset;

    for (uintptr_t i = 0; i < symtab->sh_size; i += sizeof(struct Elf32_Sym)) {
        // getting the symbol
        sym = (struct Elf32_Sym *)(symbase + i);

        // check for matching type
        if ((sym->st_info & 0x0F) != type) {
            continue;
        }

        // find the section of the associacted string table
        struct Elf32_Shdr *strtab = shead+symtab->sh_link;

        // get the pointer to the symbol name from string table + string index
        symname = (const char *)elfbase + strtab->sh_offset + sym->st_name;

        if (!contains) {
            if (strcmp(symname, name)==0) {
                /* we have a match */
                count++;
                bytes += strlen(symname)+1;
            }
        } else {
            if (strstr(symname,name) != 0) {
                count++;
                bytes += strlen(symname)+1;
            }
        }
    }

    if (ret_bytes) {
        *ret_bytes = bytes;
    }

    return count;
}