static int _decode64_strtab(AsmFormatPlugin * format, Elf64_Shdr * shdr, size_t shdr_cnt, uint16_t ndx, char ** strtab, size_t * strtab_cnt) { AsmFormatPluginHelper * helper = format->helper; ssize_t size; if(ndx >= shdr_cnt) return -error_set_code(1, "%s: %s", helper->get_filename(helper->format), "Unable to read the string table"); shdr = &shdr[ndx]; if(helper->seek(helper->format, shdr->sh_offset, SEEK_SET) < 0) return -1; size = sizeof(**strtab) * shdr->sh_size; if((*strtab = malloc(size)) == NULL) return -_elf_error(format); if(helper->read(helper->format, *strtab, size) != size) { free(*strtab); return -1; } *strtab_cnt = shdr->sh_size; return 0; }
static int _decode64_shdr(AsmFormatPlugin * format, Elf64_Ehdr * ehdr, Elf64_Shdr ** shdr) { AsmFormatPluginHelper * helper = format->helper; ssize_t size; size_t i; if(ehdr->e_shentsize == 0) { *shdr = NULL; return 0; } if(ehdr->e_shentsize != sizeof(**shdr)) return -error_set_code(1, "%s: %s", helper->get_filename(helper->format), "Invalid section header size"); if(helper->seek(helper->format, ehdr->e_shoff, SEEK_SET) < 0) return -1; size = sizeof(**shdr) * ehdr->e_shnum; if((*shdr = malloc(size)) == NULL) return -_elf_error(format); if(helper->read(helper->format, *shdr, size) != size) { free(*shdr); return -1; } if(ehdr->e_ident[EI_DATA] != elf_arch_native->endian) for(i = 0; i < ehdr->e_shnum; i++) _swap_64_shdr(*shdr + i); return 0; }
/* elf_detect */ static char const * _elf_detect(AsmFormatPlugin * format) { AsmFormatPluginHelper * helper = format->helper; char const * ret; union { Elf32_Ehdr ehdr32; Elf64_Ehdr ehdr64; } ehdr; if(helper->seek(helper->format, 0, SEEK_SET) != 0) return NULL; if(helper->read(helper->format, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) return NULL; switch(ehdr.ehdr32.e_ident[EI_CLASS]) { case ELFCLASS32: if((ret = elf32_detect(format, &ehdr.ehdr32)) != NULL) format->decode = elf32_decode; break; case ELFCLASS64: if((ret = elf64_detect(format, &ehdr.ehdr64)) != NULL) format->decode = elf64_decode; break; default: ret = NULL; error_set_code(1, "%s: %s 0x%x\n", helper->get_filename(helper->format), "Unsupported ELF class", ehdr.ehdr32.e_ident[EI_CLASS]); break; } return ret; }
static int _elf_decode32(AsmFormatPlugin * format, int raw) { AsmFormatPluginHelper * helper = format->helper; Elf32_Ehdr ehdr; Elf32_Shdr * shdr = NULL; Elf32_Addr base = 0x0; char * shstrtab = NULL; size_t shstrtab_cnt = 0; size_t i; #ifdef DEBUG fprintf(stderr, "DEBUG: %s() \"%s\"\n", __func__, helper->get_filename(helper->format)); #endif if(helper->seek(helper->format, 0, SEEK_SET) != 0 || helper->read(helper->format, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) return -1; if(ehdr.e_ident[EI_DATA] != elf_arch_native->endian) _swap_32_ehdr(&ehdr); if(_decode32_shdr(format, &ehdr, &shdr) != 0) return -1; if(_decode32_addr(format, &ehdr, &base) != 0 || _decode32_strtab(format, shdr, ehdr.e_shnum, ehdr.e_shstrndx, &shstrtab, &shstrtab_cnt) != 0) { free(shdr); return -1; } for(i = 0; i < ehdr.e_shnum; i++) if(shdr[i].sh_type == SHT_SYMTAB) { /* XXX ignore errors? */ _decode32_symtab(format, &ehdr, shdr, ehdr.e_shnum, i); break; } for(i = 0; i < ehdr.e_shnum; i++) { if(shdr[i].sh_name >= shstrtab_cnt) continue; if((raw || (shdr[i].sh_type == SHT_PROGBITS && shdr[i].sh_flags & SHF_EXECINSTR)) && helper->set_section(helper->format, i, &shstrtab[shdr[i].sh_name], shdr[i].sh_offset, shdr[i].sh_size, base + shdr[i].sh_offset) < 0) break; } free(shstrtab); free(shdr); return (i == ehdr.e_shnum) ? 0 : -1; }
static char const * _elf_detect(AsmFormatPlugin * format) { AsmFormatPluginHelper * helper = format->helper; union { Elf32_Ehdr ehdr32; Elf64_Ehdr ehdr64; } ehdr; if(helper->seek(helper->format, 0, SEEK_SET) != 0) return NULL; if(helper->read(helper->format, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) return NULL; switch(ehdr.ehdr32.e_ident[EI_CLASS]) { case ELFCLASS32: return _detect_32(format, &ehdr.ehdr32); case ELFCLASS64: return _detect_64(format, &ehdr.ehdr64); } error_set_code(1, "%s: %s 0x%x\n", helper->get_filename(helper->format), "Unsupported ELF class", ehdr.ehdr32.e_ident[EI_CLASS]); return NULL; }