/** * elf_read_from_buffer - read ELF file and sets up ELF header and ELF info * @buf: Buffer to read ELF file from. * @len: Size of @buf. * @ehdr: Pointer to existing struct which will be populated. * @elf_info: Pointer to existing struct which will be populated. * * This function allows reading ELF files with different byte order than * the kernel, byte-swapping the fields as needed. * * Return: * On success returns 0, and the caller should call elf_free_info(elf_info) to * free the memory allocated for the section and program headers. */ int elf_read_from_buffer(const char *buf, size_t len, struct elfhdr *ehdr, struct elf_info *elf_info) { int ret; ret = elf_read_ehdr(buf, len, ehdr); if (ret) return ret; elf_info->buffer = buf; elf_info->ehdr = ehdr; if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) { ret = elf_read_phdrs(buf, len, elf_info); if (ret) return ret; } if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) { ret = elf_read_shdrs(buf, len, elf_info); if (ret) { kfree(elf_info->proghdrs); return ret; } } return 0; }
int ELFManager::elf_get_section_upper_bound(unsigned int type, int *pcount) { int ret; Elf_Shdr shdrs[_ehdr.e_shnum]; ret = elf_read_shdrs(shdrs, _ehdr.e_shnum); if (ret < 0) { return -1; } int count = 0; for (unsigned int i=0; i<_ehdr.e_shnum; i++) { if (shdrs[i].sh_type == type) { count += shdrs[i].sh_size/shdrs[i].sh_entsize; } } if(pcount != NULL) { *pcount = count; } int needsize = count * sizeof(esymbol *) + count * sizeof(esymbol); return needsize; }
int ELFManager::elf_canonicalize_symbol(esymbol **symbol_table, int unsigned type) { int ret; Elf_Shdr shdrs[_ehdr.e_shnum]; ret = elf_read_shdrs(shdrs, _ehdr.e_shnum); if (ret < 0) { return -1; } unsigned int i = 0; for (; i<_ehdr.e_shnum; i++) { if (shdrs[i].sh_type == type) { break; } } if (i == _ehdr.e_shnum) { return -1; } Elf_Shdr *symtab = &shdrs[i]; //读取name Elf_Shdr *link = &shdrs[symtab->sh_link]; char *sym_name = (char *)malloc(link->sh_size); if (sym_name == NULL) { fprintf(stderr, "malloc error!\n"); return -1; } ret = elf_read(link->sh_offset, sym_name, link->sh_size); if (ret < 0) { return -1; } //读取符号表 int count = symtab->sh_size/symtab->sh_entsize; esymbol *esym = (esymbol *)&symbol_table[count]; if(_is_32_bit) { Elf32_Sym syms[count]; ret = elf_read(symtab->sh_offset, syms, symtab->sh_size); if (ret < 0) { return -1; } for (int idx=0; idx<count; idx++) { symbol_table[idx] = &esym[idx]; //printf("name:%s!, symbol_table:%llx\n", &sym_name[syms[idx].st_name], symbol_table[idx]); symbol_table[idx]->name = &sym_name[syms[idx].st_name]; //printf("debug3!\n"); symbol_table[idx]->bind = ELF32_ST_BIND(syms[idx].st_info); symbol_table[idx]->type = ELF32_ST_TYPE(syms[idx].st_info); symbol_table[idx]->shndx = syms[idx].st_shndx; symbol_table[idx]->value = syms[idx].st_value; symbol_table[idx]->size = syms[idx].st_size; } } else { Elf64_Sym syms[count]; ret = elf_read(symtab->sh_offset, syms, symtab->sh_size); if (ret < 0) { return -1; } for (int idx=0; idx<count; idx++) { symbol_table[idx] = &esym[idx]; //printf("name:%s!, symbol_table:%llx\n", &sym_name[syms[idx].st_name], symbol_table[idx]); symbol_table[idx]->name = &sym_name[syms[idx].st_name]; //printf("debug3!\n"); symbol_table[idx]->bind = ELF64_ST_BIND(syms[idx].st_info); symbol_table[idx]->type = ELF64_ST_TYPE(syms[idx].st_info); symbol_table[idx]->shndx = syms[idx].st_shndx; symbol_table[idx]->value = syms[idx].st_value; symbol_table[idx]->size = syms[idx].st_size; } } return count; }
int ELFManager::elf_canonicalize_relsym(erelsym **rel_table, int max_count) { int ret; Elf_Shdr shdrs[_ehdr.e_shnum]; ret = elf_read_shdrs(shdrs, _ehdr.e_shnum); if (ret < 0) { return -1; } int count = 0; int cur_idx = 0; erelsym *erel = (erelsym *)&rel_table[max_count]; for (unsigned int i = 0; i<_ehdr.e_shnum; i++) { if (shdrs[i].sh_type == SHT_REL || shdrs[i].sh_type == SHT_RELA) { char *rel = (char *)malloc(shdrs[i].sh_size); if (rel == NULL) { fprintf(stderr, "malloc error!\n"); return -1; } int num = shdrs[i].sh_size/shdrs[i].sh_entsize; count += num; ret = elf_read(shdrs[i].sh_offset, rel, shdrs[i].sh_size); if (ret < 0) { return -1; } if(_is_32_bit) { if (shdrs[i].sh_type==SHT_REL) { Elf32_Rel *prel = (Elf32_Rel *)rel; for (int idx=0; idx<num; idx++) { rel_table[cur_idx] = &erel[cur_idx]; rel_table[cur_idx]->offset = prel[idx].r_offset; rel_table[cur_idx]->type = ELF32_R_TYPE(prel[idx].r_info); rel_table[cur_idx]->symid = ELF32_R_SYM(prel[idx].r_info); cur_idx++; } } else { Elf32_Rela *prel = (Elf32_Rela *)rel; for (int idx=0; idx<num; idx++) { rel_table[cur_idx] = &erel[cur_idx]; rel_table[cur_idx]->offset = prel[idx].r_offset; rel_table[cur_idx]->type = ELF32_R_TYPE(prel[idx].r_info); rel_table[cur_idx]->symid = ELF32_R_SYM(prel[idx].r_info); //printf("rela[cur_idx:%d] offset:0x%lx, type:%d, symid:%d\n", // cur_idx, rel_table[cur_idx]->offset, rel_table[cur_idx]->type, rel_table[cur_idx]->symid); cur_idx++; } } } else { if (shdrs[i].sh_type==SHT_REL) { Elf64_Rel *prel = (Elf64_Rel *)rel; for (int idx=0; idx<num; idx++) { rel_table[cur_idx] = &erel[cur_idx]; rel_table[cur_idx]->offset = prel[idx].r_offset; rel_table[cur_idx]->type = ELF64_R_TYPE(prel[idx].r_info); rel_table[cur_idx]->symid = ELF64_R_SYM(prel[idx].r_info); cur_idx++; } } else { Elf64_Rela *prel = (Elf64_Rela *)rel; for (int idx=0; idx<num; idx++) { rel_table[cur_idx] = &erel[cur_idx]; rel_table[cur_idx]->offset = prel[idx].r_offset; rel_table[cur_idx]->type = ELF64_R_TYPE(prel[idx].r_info); rel_table[cur_idx]->symid = ELF64_R_SYM(prel[idx].r_info); //printf("rela[cur_idx:%d] offset:0x%lx, type:%d, symid:%d\n", // cur_idx, rel_table[cur_idx]->offset, rel_table[cur_idx]->type, rel_table[cur_idx]->symid); cur_idx++; } } } if(rel) { free(rel); } } } return count; }