static struct mem_sym elf_sym(struct mem_ehdr *ehdr, const unsigned char *ptr) { struct mem_sym sym = { }; if (ehdr->ei_class == ELFCLASS32) { Elf32_Sym lsym; memcpy(&lsym, ptr, sizeof(lsym)); sym.st_name = elf32_to_cpu(ehdr, lsym.st_name); sym.st_value = elf32_to_cpu(ehdr, lsym.st_value); sym.st_size = elf32_to_cpu(ehdr, lsym.st_size); sym.st_info = lsym.st_info; sym.st_other = lsym.st_other; sym.st_shndx = elf16_to_cpu(ehdr, lsym.st_shndx); } else if (ehdr->ei_class == ELFCLASS64) { Elf64_Sym lsym; memcpy(&lsym, ptr, sizeof(lsym)); sym.st_name = elf32_to_cpu(ehdr, lsym.st_name); sym.st_value = elf64_to_cpu(ehdr, lsym.st_value); sym.st_size = elf64_to_cpu(ehdr, lsym.st_size); sym.st_info = lsym.st_info; sym.st_other = lsym.st_other; sym.st_shndx = elf16_to_cpu(ehdr, lsym.st_shndx); } else { die("Bad elf class"); } return sym; }
static struct mem_rela elf_rel(struct mem_ehdr *ehdr, const unsigned char *ptr) { struct mem_rela rela = { }; if (ehdr->ei_class == ELFCLASS32) { Elf32_Rel lrel; memcpy(&lrel, ptr, sizeof(lrel)); rela.r_offset = elf32_to_cpu(ehdr, lrel.r_offset); rela.r_sym = ELF32_R_SYM(elf32_to_cpu(ehdr, lrel.r_info)); rela.r_type = ELF32_R_TYPE(elf32_to_cpu(ehdr, lrel.r_info)); rela.r_addend = 0; } else if (ehdr->ei_class == ELFCLASS64) { Elf64_Rel lrel; memcpy(&lrel, ptr, sizeof(lrel)); rela.r_offset = elf64_to_cpu(ehdr, lrel.r_offset); rela.r_sym = ELF64_R_SYM(elf64_to_cpu(ehdr, lrel.r_info)); rela.r_type = ELF64_R_TYPE(elf64_to_cpu(ehdr, lrel.r_info)); rela.r_addend = 0; } else { die("Bad elf class"); } return rela; }
static int build_mem_elf64_shdr(const char *buf, off_t len, struct mem_ehdr *ehdr, int idx) { struct mem_shdr *shdr; const char *sbuf; int size_ok; Elf64_Shdr lshdr; sbuf = buf + ehdr->e_shoff + (idx * sizeof(lshdr)); shdr = &ehdr->e_shdr[idx]; memcpy(&lshdr, sbuf, sizeof(lshdr)); if ( (elf64_to_cpu(ehdr, lshdr.sh_flags) > UINT64_MAX) || (elf64_to_cpu(ehdr, lshdr.sh_addr) > UINT64_MAX) || (elf64_to_cpu(ehdr, lshdr.sh_offset) > UINT64_MAX) || (elf64_to_cpu(ehdr, lshdr.sh_size) > UINT64_MAX) || (elf64_to_cpu(ehdr, lshdr.sh_addralign) > UINT64_MAX) || (elf64_to_cpu(ehdr, lshdr.sh_entsize) > UINT64_MAX)) { fprintf(stderr, "Program section size out of range\n"); return -1; } shdr->sh_name = elf32_to_cpu(ehdr, lshdr.sh_name); shdr->sh_type = elf32_to_cpu(ehdr, lshdr.sh_type); shdr->sh_flags = elf64_to_cpu(ehdr, lshdr.sh_flags); shdr->sh_addr = elf64_to_cpu(ehdr, lshdr.sh_addr); shdr->sh_offset = elf64_to_cpu(ehdr, lshdr.sh_offset); shdr->sh_size = elf64_to_cpu(ehdr, lshdr.sh_size); shdr->sh_link = elf32_to_cpu(ehdr, lshdr.sh_link); shdr->sh_info = elf32_to_cpu(ehdr, lshdr.sh_info); shdr->sh_addralign = elf64_to_cpu(ehdr, lshdr.sh_addralign); shdr->sh_entsize = elf64_to_cpu(ehdr, lshdr.sh_entsize); /* Now verify sh_entsize */ size_ok = 0; switch(shdr->sh_type) { case SHT_SYMTAB: size_ok = shdr->sh_entsize == sizeof(Elf64_Sym); break; case SHT_RELA: size_ok = shdr->sh_entsize == sizeof(Elf64_Rela); break; case SHT_DYNAMIC: size_ok = shdr->sh_entsize == sizeof(Elf64_Dyn); break; case SHT_REL: size_ok = shdr->sh_entsize == sizeof(Elf64_Rel); break; case SHT_NOTE: case SHT_NULL: case SHT_PROGBITS: case SHT_HASH: case SHT_NOBITS: default: /* This is a section whose entsize requirements * I don't care about. If I don't know about * the section I can't care about it's entsize * requirements. */ size_ok = 1; break; } if (!size_ok) { fprintf(stderr, "Bad section header(%x) entsize: %ld\n", shdr->sh_type, shdr->sh_entsize); return -1; } return 0; }
static int build_mem_elf64_phdr(const char *buf, off_t len, struct mem_ehdr *ehdr, int idx) { struct mem_phdr *phdr; const char *pbuf; Elf64_Phdr lphdr; pbuf = buf + ehdr->e_phoff + (idx * sizeof(lphdr)); phdr = &ehdr->e_phdr[idx]; memcpy(&lphdr, pbuf, sizeof(lphdr)); if ( (elf64_to_cpu(ehdr, lphdr.p_filesz) > UINT64_MAX) || (elf64_to_cpu(ehdr, lphdr.p_memsz) > UINT64_MAX) || (elf64_to_cpu(ehdr, lphdr.p_offset) > UINT64_MAX) || (elf64_to_cpu(ehdr, lphdr.p_paddr) > UINT64_MAX) || (elf64_to_cpu(ehdr, lphdr.p_vaddr) > UINT64_MAX) || (elf64_to_cpu(ehdr, lphdr.p_align) > UINT64_MAX)) { fprintf(stderr, "Program segment size out of range\n"); return -1; } phdr->p_type = elf32_to_cpu(ehdr, lphdr.p_type); phdr->p_paddr = elf64_to_cpu(ehdr, lphdr.p_paddr); phdr->p_vaddr = elf64_to_cpu(ehdr, lphdr.p_vaddr); phdr->p_filesz = elf64_to_cpu(ehdr, lphdr.p_filesz); phdr->p_memsz = elf64_to_cpu(ehdr, lphdr.p_memsz); phdr->p_offset = elf64_to_cpu(ehdr, lphdr.p_offset); phdr->p_flags = elf32_to_cpu(ehdr, lphdr.p_flags); phdr->p_align = elf64_to_cpu(ehdr, lphdr.p_align); return 0; }
static int build_mem_elf64_ehdr(const char *buf, off_t len, struct mem_ehdr *ehdr) { Elf64_Ehdr lehdr; if (len < sizeof(lehdr)) { /* Buffer is to small to be an elf executable */ if (probe_debug) { fprintf(stderr, "Buffer is to small to hold ELF header\n"); } return -1; } memcpy(&lehdr, buf, sizeof(lehdr)); if (elf16_to_cpu(ehdr, lehdr.e_ehsize) != sizeof(Elf64_Ehdr)) { /* Invalid Elf header size */ if (probe_debug) { fprintf(stderr, "Bad ELF header size\n"); } return -1; } if (elf32_to_cpu(ehdr, lehdr.e_entry) > UINT32_MAX) { /* entry is to large */ if (probe_debug) { fprintf(stderr, "ELF e_entry to large\n"); } return -1; } if (elf32_to_cpu(ehdr, lehdr.e_phoff) > UINT32_MAX) { /* phoff is to large */ if (probe_debug) { fprintf(stderr, "ELF e_phoff to large\n"); } return -1; } if (elf32_to_cpu(ehdr, lehdr.e_shoff) > UINT32_MAX) { /* shoff is to large */ if (probe_debug) { fprintf(stderr, "ELF e_shoff to large\n"); } return -1; } ehdr->e_type = elf16_to_cpu(ehdr, lehdr.e_type); ehdr->e_machine = elf16_to_cpu(ehdr, lehdr.e_machine); ehdr->e_version = elf32_to_cpu(ehdr, lehdr.e_version); ehdr->e_entry = elf64_to_cpu(ehdr, lehdr.e_entry); ehdr->e_phoff = elf64_to_cpu(ehdr, lehdr.e_phoff); ehdr->e_shoff = elf64_to_cpu(ehdr, lehdr.e_shoff); ehdr->e_flags = elf32_to_cpu(ehdr, lehdr.e_flags); ehdr->e_phnum = elf16_to_cpu(ehdr, lehdr.e_phnum); ehdr->e_shnum = elf16_to_cpu(ehdr, lehdr.e_shnum); ehdr->e_shstrndx = elf16_to_cpu(ehdr, lehdr.e_shstrndx); if ((ehdr->e_phnum > 0) && (elf16_to_cpu(ehdr, lehdr.e_phentsize) != sizeof(Elf64_Phdr))) { /* Invalid program header size */ if (probe_debug) { fprintf(stderr, "ELF bad program header size\n"); } return -1; } if ((ehdr->e_shnum > 0) && (elf16_to_cpu(ehdr, lehdr.e_shentsize) != sizeof(Elf64_Shdr))) { /* Invalid section header size */ if (probe_debug) { fprintf(stderr, "ELF bad section header size\n"); } return -1; } return 0; }