Beispiel #1
0
Elf_Scn*
elf_nextscn(Elf *elf, Elf_Scn *scn) {
    if (!elf) {
	return NULL;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (scn) {
	elf_assert(scn->s_magic == SCN_MAGIC);
	if (scn->s_elf == elf) {
	    return scn->s_link;
	}
	seterr(ERROR_ELFSCNMISMATCH);
    }
    else if (elf->e_kind != ELF_K_ELF) {
	seterr(ERROR_NOTELF);
    }
    else if (elf->e_ehdr || _elf_cook(elf)) {
	elf_assert(elf->e_ehdr);
	for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
	    elf_assert(scn->s_magic == SCN_MAGIC);
	    elf_assert(scn->s_elf == elf);
	    if (scn->s_index == 1) {
		return scn;
	    }
	}
	seterr(ERROR_NOSUCHSCN);
    }
    return NULL;
}
Beispiel #2
0
int
elf_getshstrndx(Elf *elf, size_t *resultp) {
    size_t num = 0;
    size_t dummy;
    Elf_Scn *scn;

    if (!elf) {
	return LIBELF_FAILURE;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (resultp == NULL) {
	resultp = &dummy;	/* handle NULL pointer gracefully */
    }
    if (elf->e_kind != ELF_K_ELF) {
	seterr(ERROR_NOTELF);
	return LIBELF_FAILURE;
    }
    if (!elf->e_ehdr && !_elf_cook(elf)) {
	return LIBELF_FAILURE;
    }
    if (elf->e_class == ELFCLASS32) {
	num = ((Elf32_Ehdr*)elf->e_ehdr)->e_shstrndx;
    }
#if __LIBELF64
    else if (elf->e_class == ELFCLASS64) {
	num = ((Elf64_Ehdr*)elf->e_ehdr)->e_shstrndx;
    }
#endif /* __LIBELF64 */
    else {
	if (valid_class(elf->e_class)) {
	    seterr(ERROR_UNIMPLEMENTED);
	}
	else {
	    seterr(ERROR_UNKNOWN_CLASS);
	}
	return LIBELF_FAILURE;
    }
    if (num != SHN_XINDEX) {
	*resultp = num;
	return LIBELF_SUCCESS;
    }
    /*
     * look at first section header
     */
    if (!(scn = elf->e_scn_1)) {
	seterr(ERROR_NOSUCHSCN);
	return LIBELF_FAILURE;
    }
    elf_assert(scn->s_magic == SCN_MAGIC);
#if __LIBELF64
    if (elf->e_class == ELFCLASS64) {
	*resultp = scn->s_shdr64.sh_link;
	return LIBELF_SUCCESS;
    }
#endif /* __LIBELF64 */
    *resultp = scn->s_shdr32.sh_link;
    return LIBELF_SUCCESS;
}
Beispiel #3
0
static char*
_elf_newphdr(Elf *elf, size_t count, unsigned cls) {
    char *phdr = NULL;
    size_t size;

    if (!elf) {
	return NULL;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (!elf->e_ehdr && !elf->e_readable) {
	seterr(ERROR_NOEHDR);
    }
    else if (elf->e_kind != ELF_K_ELF) {
	seterr(ERROR_NOTELF);
    }
    else if (elf->e_class != cls) {
	seterr(ERROR_CLASSMISMATCH);
    }
    else if (elf->e_ehdr || _elf_cook(elf)) {
	size = _msize(cls, _elf_version, ELF_T_PHDR);
	elf_assert(size);
	if (count) {
	    if (!(phdr = (char*)malloc(count * size))) {
		seterr(ERROR_MEM_PHDR);
		return NULL;
	    }
	    memset(phdr, 0, count * size);
	}
	elf_assert(elf->e_ehdr);
	if (cls == ELFCLASS32) {
	    ((Elf32_Ehdr*)elf->e_ehdr)->e_phnum = elf->e_phnum = count;
	}
#if __LIBELF64
	else if (cls == ELFCLASS64) {
	    ((Elf64_Ehdr*)elf->e_ehdr)->e_phnum = elf->e_phnum = count;
	}
#endif /* __LIBELF64 */
	else {
	    seterr(ERROR_UNIMPLEMENTED);
	    if (phdr) {
		free(phdr);
	    }
	    return NULL;
	}
	if (elf->e_free_phdr) {
	    elf_assert(elf->e_phdr);
	    free(elf->e_phdr);
	}
	elf->e_phdr = phdr;
	elf->e_free_phdr = phdr ? 1 : 0;
	elf->e_phdr_flags |= ELF_F_DIRTY;
	elf->e_ehdr_flags |= ELF_F_DIRTY;
	return phdr;
    }
    return NULL;
}
Beispiel #4
0
char *_elf_getphdr(Elf * elf, unsigned cls)
{
	if (!elf) {
		return NULL;
	}
	elf_assert(elf->e_magic == ELF_MAGIC);
	if (elf->e_kind != ELF_K_ELF) {
		seterr(ERROR_NOTELF);
	} else if (elf->e_class != cls) {
		seterr(ERROR_CLASSMISMATCH);
	} else if (elf->e_ehdr || _elf_cook(elf)) {
		return elf->e_phdr;
	}
	return NULL;
}
Beispiel #5
0
int
elfx_update_shstrndx(Elf *elf, size_t value) {
    size_t extvalue = 0;
    Elf_Scn *scn;

    if (!elf) {
	return LIBELF_FAILURE;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (value >= SHN_LORESERVE) {
	extvalue = value;
	value = SHN_XINDEX;
    }
    if (elf->e_kind != ELF_K_ELF) {
	seterr(ERROR_NOTELF);
	return LIBELF_FAILURE;
    }
    if (!elf->e_ehdr && !_elf_cook(elf)) {
	return LIBELF_FAILURE;
    }
    if (!(scn = _elf_first_scn(elf))) {
	return LIBELF_FAILURE;
    }
    elf_assert(scn->s_magic == SCN_MAGIC);
    if (elf->e_class == ELFCLASS32) {
	((Elf32_Ehdr*)elf->e_ehdr)->e_shstrndx = value;
	scn->s_shdr32.sh_link = extvalue;
    }
#if __LIBELF64
    else if (elf->e_class == ELFCLASS64) {
	((Elf64_Ehdr*)elf->e_ehdr)->e_shstrndx = value;
	scn->s_shdr64.sh_link = extvalue;
    }
#endif /* __LIBELF64 */
    else {
	if (valid_class(elf->e_class)) {
	    seterr(ERROR_UNIMPLEMENTED);
	}
	else {
	    seterr(ERROR_UNKNOWN_CLASS);
	}
	return LIBELF_FAILURE;
    }
    elf->e_ehdr_flags |= ELF_F_DIRTY;
    scn->s_shdr_flags |= ELF_F_DIRTY;
    return LIBELF_SUCCESS;
}
Beispiel #6
0
int
elf_cntl(Elf *elf, Elf_Cmd cmd) {
    Elf_Scn *scn;
    Elf *child;

    if (!elf) {
	return -1;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (cmd == ELF_C_FDREAD) {
	if (!elf->e_readable) {
	    seterr(ERROR_WRONLY);
	    return -1;
	}
    }
    else if (cmd != ELF_C_FDDONE) {
	seterr(ERROR_INVALID_CMD);
	return -1;
    }
    if (elf->e_disabled) {
	return 0;
    }
    if (elf->e_kind == ELF_K_AR) {
	for (child = elf->e_members; child; child = child->e_link) {
	    elf_assert(elf == child->e_parent);
	    if (elf_cntl(child, cmd)) {
		return -1;
	    }
	}
    }
    else if (elf->e_kind == ELF_K_ELF && cmd == ELF_C_FDREAD) {
	if (!elf->e_ehdr && !_elf_cook(elf)) {
	    return -1;
	}
	for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
	    if (scn->s_index == SHN_UNDEF || scn->s_type == SHT_NULL) {
		continue;
	    }
	    else if (!elf_getdata(scn, NULL)) {
		return -1;
	    }
	}
    }
    elf->e_disabled = 1;
    return 0;
}
Beispiel #7
0
int
elf_getphnum(Elf *elf, size_t *resultp) {
    if (!elf) {
	return LIBELF_FAILURE;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (elf->e_kind != ELF_K_ELF) {
	seterr(ERROR_NOTELF);
	return LIBELF_FAILURE;
    }
    if (!elf->e_ehdr && !_elf_cook(elf)) {
	return LIBELF_FAILURE;
    }
    if (resultp) {
	*resultp = elf->e_phnum;
    }
    return LIBELF_SUCCESS;
}
Beispiel #8
0
Elf_Scn*
elf_newscn(Elf *elf) {
    Elf_Scn *scn;

    if (!elf) {
	return NULL;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (!elf->e_readable && !elf->e_ehdr) {
	seterr(ERROR_NOEHDR);
    }
    else if (elf->e_kind != ELF_K_ELF) {
	seterr(ERROR_NOTELF);
    }
    else if (!elf->e_ehdr && !_elf_cook(elf)) {
	return NULL;
    }
    else if ((scn = _buildscn(elf))) {
	return scn;
    }
    return NULL;
}
Beispiel #9
0
Elf_Scn*
elf_getscn(Elf *elf, size_t index) {
    Elf_Scn *scn;

    if (!elf) {
	return NULL;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (elf->e_kind != ELF_K_ELF) {
	seterr(ERROR_NOTELF);
    }
    else if (elf->e_ehdr || _elf_cook(elf)) {
	for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
	    elf_assert(scn->s_magic == SCN_MAGIC);
	    elf_assert(scn->s_elf == elf);
	    if (scn->s_index == index) {
		return scn;
	    }
	}
	seterr(ERROR_NOSUCHSCN);
    }
    return NULL;
}
Beispiel #10
0
char*
elf_getident(Elf *elf, size_t *ptr) {
    size_t tmp;

    if (!ptr) {
        ptr = &tmp;
    }
    if (!elf) {
        *ptr = 0;
        return NULL;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (elf->e_kind != ELF_K_ELF) {
        *ptr = elf->e_idlen;
        return elf->e_data;
    }
    if (elf->e_ehdr || _elf_cook(elf)) {
        *ptr = elf->e_idlen;
        return elf->e_ehdr;
    }
    *ptr = 0;
    return NULL;
}
Beispiel #11
0
int
elf_getshnum(Elf *elf, size_t *resultp) {
    size_t num = 0;
    Elf_Scn *scn;

    if (!elf) {
	return LIBELF_FAILURE;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (elf->e_kind != ELF_K_ELF) {
	seterr(ERROR_NOTELF);
	return LIBELF_FAILURE;
    }
    if (!elf->e_ehdr && !_elf_cook(elf)) {
	return LIBELF_FAILURE;
    }
    if ((scn = elf->e_scn_n)) {
	num = scn->s_index + 1;
    }
    if (resultp) {
	*resultp = num;
    }
    return LIBELF_SUCCESS;
}
Beispiel #12
0
static char*
_elf_newphdr(Elf *elf, size_t count, unsigned cls) {
    size_t extcount = 0;
    Elf_Scn *scn = NULL;
    char *phdr = NULL;
    size_t size;

    if (!elf) {
	return NULL;
    }
    elf_assert(elf->e_magic == ELF_MAGIC);
    if (!elf->e_ehdr && !elf->e_readable) {
	seterr(ERROR_NOEHDR);
    }
    else if (elf->e_kind != ELF_K_ELF) {
	seterr(ERROR_NOTELF);
    }
    else if (elf->e_class != cls) {
	seterr(ERROR_CLASSMISMATCH);
    }
    else if (elf->e_ehdr || _elf_cook(elf)) {
	size = _msize(cls, _elf_version, ELF_T_PHDR);
	elf_assert(size);
	if (!(scn = _elf_first_scn(elf))) {
	    return NULL;
	}
	if (count) {
	    if (!(phdr = (char*)malloc(count * size))) {
		seterr(ERROR_MEM_PHDR);
		return NULL;
	    }
	    memset(phdr, 0, count * size);
	}
	elf_assert(elf->e_ehdr);
	elf->e_phnum = count;
	if (count >= PN_XNUM) {
	    /*
	     * get NULL section (create it if necessary)
	     */
	    extcount = count;
	    count = PN_XNUM;
	}
	if (cls == ELFCLASS32) {
	    ((Elf32_Ehdr*)elf->e_ehdr)->e_phnum = count;
	    scn->s_shdr32.sh_info = extcount;
	}
#if __LIBELF64
	else if (cls == ELFCLASS64) {
	    ((Elf64_Ehdr*)elf->e_ehdr)->e_phnum = count;
	    scn->s_shdr64.sh_info = extcount;
	}
#endif /* __LIBELF64 */
	else {
	    seterr(ERROR_UNIMPLEMENTED);
	    if (phdr) {
		free(phdr);
	    }
	    return NULL;
	}
	if (elf->e_phdr) {
	    free(elf->e_phdr);
	}
	elf->e_phdr = phdr;
	elf->e_phdr_flags |= ELF_F_DIRTY;
	elf->e_ehdr_flags |= ELF_F_DIRTY;
	scn->s_scn_flags |= ELF_F_DIRTY;
	return phdr;
    }
    return NULL;
}
Beispiel #13
0
static int
_elf_nlist(Elf *elf, struct nlist *nl) {
    unsigned first[PRIME];
    Elf_Scn *symtab = NULL;
    Elf_Scn *strtab = NULL;
    Elf_Data *symdata;
    Elf_Data *strdata;
    size_t symsize;
    size_t nsymbols;
    const char *name;
    struct hash *table;
    unsigned long hash;
    unsigned i;
    struct nlist *np;

    /*
     * Get and translate ELF header, section table and so on.
     * Must be class independent, so don't use elf32_get*().
     */
    if (elf->e_kind != ELF_K_ELF) {
	return -1;
    }
    if (!elf->e_ehdr && !_elf_cook(elf)) {
	return -1;
    }

    /*
     * Find symbol table. If there is none, try dynamic symbols.
     */
    for (symtab = elf->e_scn_1; symtab; symtab = symtab->s_link) {
	if (symtab->s_type == SHT_SYMTAB) {
	    break;
	}
	if (symtab->s_type == SHT_DYNSYM) {
	    strtab = symtab;
	}
    }
    if (!symtab && !(symtab = strtab)) {
	return -1;
    }

    /*
     * Get associated string table.
     */
    i = 0;
    if (elf->e_class == ELFCLASS32) {
	i = symtab->s_shdr32.sh_link;
    }
#if __LIBELF64
    else if (elf->e_class == ELFCLASS64) {
	i = symtab->s_shdr64.sh_link;
    }
#endif /* __LIBELF64 */
    if (i == 0) {
	return -1;
    }
    for (strtab = elf->e_scn_1; strtab; strtab = strtab->s_link) {
	if (strtab->s_index == i) {
	    break;
	}
    }
    if (!strtab || strtab->s_type != SHT_STRTAB) {
	return -1;
    }

    /*
     * Get and translate section data.
     */
    symdata = elf_getdata(symtab, NULL);
    strdata = elf_getdata(strtab, NULL);
    if (!symdata || !strdata) {
	return -1;
    }
    symsize = _msize(elf->e_class, _elf_version, ELF_T_SYM);
    elf_assert(symsize);
    nsymbols = symdata->d_size / symsize;
    if (!symdata->d_buf || !strdata->d_buf || !nsymbols || !strdata->d_size) {
	return -1;
    }

    /*
     * Build a simple hash table.
     */
    if (!(table = (struct hash*)malloc(nsymbols * sizeof(*table)))) {
	return -1;
    }
    for (i = 0; i < PRIME; i++) {
	first[i] = 0;
    }
    for (i = 0; i < nsymbols; i++) {
	table[i].name = NULL;
	table[i].hash = 0;
	table[i].next = 0;
    }
    for (i = 1; i < nsymbols; i++) {
	name = symbol_name(elf, symdata->d_buf, strdata->d_buf,
			   strdata->d_size, i);
	if (name == NULL) {
	    free(table);
	    return -1;
	}
	if (*name != '\0') {
	    table[i].name = name;
	    table[i].hash = elf_hash((unsigned char *) name);
	    hash = table[i].hash % PRIME;
	    table[i].next = first[hash];
	    first[hash] = i;
	}
    }

    /*
     * Lookup symbols, one by one.
     */
    for (np = nl; (name = np->n_name) && *name; np++) {
	hash = elf_hash((unsigned char *) name);
	for (i = first[hash % PRIME]; i; i = table[i].next) {
	    if (table[i].hash == hash && !strcmp(table[i].name, name)) {
		break;
	    }
	}
	if (i) {
	    copy_symbol(elf, np, symdata->d_buf, i);
	}
	else {
	    np->n_value = 0;
	    np->n_scnum = 0;
	    np->n_type = 0;
	    np->n_sclass = 0;
	    np->n_numaux = 0;
	}
    }
    free(table);
    return 0;
}