コード例 #1
0
ファイル: elf.c プロジェクト: iankronquist/kernel-of-truth
const char *elf_get_shared_object_name(const struct elf64_header *header,
                                       const size_t size) {
    const uint8_t *start = (const uint8_t *)header;
    if (!elf_verify(header, size) || elf_verify_shared_object(header)) {
        return NULL;
    }

    size_t dynamic_size;
    const struct elf_dyn *dynamic = elf_get_section(header, size, ".dynamic",
                                                    &dynamic_size);
    if (dynamic == NULL || (uint8_t *)dynamic + dynamic_size > start + size) {
        return NULL;
    }

    size_t dynstrtab_size;
    const char *dynstrtab = elf_get_section(header, size, ".dynstr",
                                            &dynstrtab_size);
    if (dynstrtab == NULL ||
        (uint8_t *)dynstrtab + dynstrtab_size > start + size) {
        return NULL;
    }

    for (size_t i = 0; i < dynamic_size / sizeof(struct elf_dyn); ++i) {
        if (dynamic[i].d_tag == DT_SONAME) {
            const char *soname = dynstrtab + dynamic[i].d_un.d_val;
            if (soname > dynstrtab + dynstrtab_size) {
                return NULL;
            }
            return soname;
        }
    }

    return NULL;
}
コード例 #2
0
ファイル: elf.c プロジェクト: iankronquist/kernel-of-truth
void *elf_get_symbol_address(void *elf, size_t size, const char *name) {
    const struct elf_section_header *section;
    void *base;
    void *location;
    size_t strtab_size;
    const char *strtab = elf_get_section(elf, size, ".strtab", &strtab_size);
    if (strtab == NULL) {
        log(Log_Error, "Could not find strtab");
        return NULL;
    }
    size_t symtab_size;
    const struct elf_symbol *symtab = elf_get_section(elf, size, ".symtab", &symtab_size);
    if (symtab == NULL) {
        log(Log_Error, "Could not find symtab");
        return NULL;
    }

    base = elf_get_base_address(elf, size);
    if (base == NULL) {
        log(Log_Error, "Bad base");
        return NULL;
    }

    for (size_t i = 0; i < symtab_size / sizeof(struct elf_symbol); ++i) {

        if (ELF64_R_TYPE(symtab[i].st_info) != STT_FILE) {

            const char *symbol_name = &strtab[symtab[i].st_name];
            if ((void *)symbol_name > elf + size) {
                log(Log_Error, "Symbol name out of bounds");
                return NULL;
            }

            section = elf_get_section_index(elf, size, symtab[i].st_index);
            if (section == NULL) {
                log(Log_Error, "Bad symbol index");
                return NULL;
            }

            if (strncmp(symbol_name, name, strlen(name)) == 0) {
                location = base + symtab[i].st_value;
                if (location > elf + size) {
                    logf(Log_Error, "Location out of bound %p %p\n", location, elf + size);
                    return NULL;
                }
                return location;
            }
        }
    }

    return NULL;
}
コード例 #3
0
ファイル: elf_get_section_r.c プロジェクト: rsenn/dirlist
range
elf_get_section_r(void* elf, const char* name) {
  range r;
  r.start = elf_get_section(elf, name, &r.elem_size);
  r.end = r.start + r.elem_size;
  return r;
}
コード例 #4
0
ファイル: elf.c プロジェクト: iankronquist/kernel-of-truth
static enum status elf_run_init_fini_helper(void *module_start, size_t module_size, int dt_array, int dt_array_size) {
    void *base;
    size_t funcs_size = 0;
    bool funcs_size_found = false;
    enum status (**funcs)(void) = NULL;
    size_t dynamic_size;
    const struct elf_dyn *dynamic = elf_get_section(module_start, module_size, ".dynamic", &dynamic_size);
    if (dynamic == NULL) {
        log(Log_Error, "Couldn't find section .dynamic");
        return Error_Invalid;
    }

    base = elf_get_base_address(module_start, module_size);
    if (base == NULL) {
        log(Log_Error, "Bad base");
        return Error_Invalid;
    }

    for (size_t i = 0; i < dynamic_size / sizeof(struct elf_dyn); ++i) {
        if (dynamic[i].d_tag == dt_array) {
            funcs = base + dynamic[i].d_un.d_ptr;
        } else if (dynamic[i].d_tag == dt_array_size) {
            funcs_size = dynamic[i].d_un.d_val;
            funcs_size_found = true;
        }

        if (funcs != NULL && funcs_size_found) {
            break;
        }
    }


    if (funcs == NULL || !funcs_size_found) {
        log(Log_Info, "Module has no init/fini");
        return Ok;
    } else if ((void *)funcs + funcs_size > module_start + module_size) {
        log(Log_Info, "Module init/fini out of bounds");
        return Error_Invalid;
    }


    for (size_t i = 0; i < funcs_size / sizeof(enum status (*)(void)); ++i) {
        enum status status = funcs[i]();
        if (status != Ok) {
            return status;
        }
    }

    return Ok;
}
コード例 #5
0
ファイル: elf.c プロジェクト: iankronquist/kernel-of-truth
enum status elf_relocate(void *module_start, size_t module_size) {
    int64_t *pointer;
    int64_t value;
    const struct elf_symbol *symbol;
    size_t rela_size;
    const struct elf_rela *rela;
    size_t dynsym_size;
    const struct elf_symbol *dynsym;
    size_t dynstr_size;
    void *base;
    const char *dynstr = elf_get_section(module_start,
                                         module_size,
                                         ".dynstr",
                                         &dynstr_size);
    if (dynstr == NULL) {
        log(Log_Error, "Couldn't find section .dynstr");
        return Error_Invalid;
    }

    rela = elf_get_section(module_start, module_size, ".rela.dyn", &rela_size);
    if (rela == NULL) {
        log(Log_Error, "Couldn't find section .rela.dyn");
        return Error_Invalid;
    }

    dynsym = elf_get_section(module_start, module_size, ".dynsym",
                              &dynsym_size);
    if (dynsym == NULL) {
        log(Log_Error, "Couldn't find section .dynsym");
        return Error_Invalid;
    }

    rela = elf_get_section(module_start, module_size, ".rela.dyn", &rela_size);
    if (rela == NULL) {
        log(Log_Error, "Couldn't find section .rela.dyn");
        return Error_Invalid;
    }

    base = elf_get_base_address(module_start, module_size);
    if (base == NULL) {
        log(Log_Error, "Bad base");
        return Error_Invalid;
    }

    for (size_t i = 0; i < rela_size / sizeof(struct elf_rela); ++i) {
        int r_type = ELF64_R_TYPE(rela[i].r_info);
        switch (r_type) {
            case R_X86_64_RELATIVE:
                pointer = module_start + rela[i].r_offset;
                value = (uintptr_t)base + rela[i].r_addend;
                *pointer = value;
                break;
            case R_X86_64_JUMP_SLOT:
            case R_X86_64_GLOB_DAT:
            case R_X86_64_64:
                symbol = &dynsym[ELF64_R_SYM(rela[i].r_info)];
                if ((void *)(symbol + 1) > module_start + module_size) {
                    logf(Log_Error, "Symbol out of bounds\n");
                    return Error_Invalid;
                }
                pointer = base + rela[i].r_offset;
                if (symbol->st_index == SHN_UNDEF) {
                    if ((void *)&dynsym[symbol->st_name] > module_start + module_size) {
                        log(Log_Error, "String out of bounds");
                        return Error_Invalid;
                    }

                    value = (uintptr_t)symbol_get(&dynstr[symbol->st_name]);
                    if (value == 0) {
                        logf(Log_Error, "External symbol %s not loaded\n", &dynstr[symbol->st_name]);
                        return Error_Invalid;
                    }
                } else if (r_type == R_X86_64_64) {
                    value = (uintptr_t)base + symbol->st_value + rela[i].r_addend;
                } else {
                    value = (uintptr_t)base + symbol->st_value;
                }
                *pointer = value;
                break;
            default:
                logf(Log_Error, "Unable to resolve rela symbol of type %lx\n", rela[i].r_info);
                return Error_Invalid;
        }
    }

    return Ok;
}