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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }