Пример #1
0
/**
 * 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;
}
Пример #2
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}