// read symbol table from given fd. struct symtab* build_symtab(int fd) { ELF_EHDR ehdr; struct symtab* symtab = NULL; // Reading of elf header struct elf_section *scn_cache = NULL; int cnt = 0; ELF_SHDR* shbuf = NULL; ELF_SHDR* cursct = NULL; ELF_PHDR* phbuf = NULL; int symtab_found = 0; int dynsym_found = 0; uint32_t symsection = SHT_SYMTAB; uintptr_t baseaddr = (uintptr_t)-1; lseek(fd, (off_t)0L, SEEK_SET); if (! read_elf_header(fd, &ehdr)) { // not an elf return NULL; } // read ELF header if ((shbuf = read_section_header_table(fd, &ehdr)) == NULL) { goto quit; } baseaddr = find_base_address(fd, &ehdr); scn_cache = calloc(ehdr.e_shnum, sizeof(*scn_cache)); if (scn_cache == NULL) { goto quit; } for (cursct = shbuf, cnt = 0; cnt < ehdr.e_shnum; cnt++) { scn_cache[cnt].c_shdr = cursct; if (cursct->sh_type == SHT_SYMTAB || cursct->sh_type == SHT_STRTAB || cursct->sh_type == SHT_DYNSYM) { if ( (scn_cache[cnt].c_data = read_section_data(fd, &ehdr, cursct)) == NULL) { goto quit; } } if (cursct->sh_type == SHT_SYMTAB) symtab_found++; if (cursct->sh_type == SHT_DYNSYM) dynsym_found++; cursct++; } if (!symtab_found && dynsym_found) symsection = SHT_DYNSYM; for (cnt = 1; cnt < ehdr.e_shnum; cnt++) { ELF_SHDR *shdr = scn_cache[cnt].c_shdr; if (shdr->sh_type == symsection) { ELF_SYM *syms; int j, n; size_t size; // FIXME: there could be multiple data buffers associated with the // same ELF section. Here we can handle only one buffer. See man page // for elf_getdata on Solaris. // guarantee(symtab == NULL, "multiple symtab"); symtab = calloc(1, sizeof(*symtab)); if (symtab == NULL) { goto quit; } // the symbol table syms = (ELF_SYM *)scn_cache[cnt].c_data; // number of symbols n = shdr->sh_size / shdr->sh_entsize; // create hash table, we use berkeley db to // manipulate the hash table. symtab->hash_table = dbopen(NULL, O_CREAT | O_RDWR, 0600, DB_HASH, NULL); // guarantee(symtab->hash_table, "unexpected failure: dbopen"); if (symtab->hash_table == NULL) goto bad; // shdr->sh_link points to the section that contains the actual strings // for symbol names. the st_name field in ELF_SYM is just the // string table index. we make a copy of the string table so the // strings will not be destroyed by elf_end. size = scn_cache[shdr->sh_link].c_shdr->sh_size; symtab->strs = malloc(size); if (symtab->strs == NULL) goto bad; memcpy(symtab->strs, scn_cache[shdr->sh_link].c_data, size); // allocate memory for storing symbol offset and size; symtab->num_symbols = n; symtab->symbols = calloc(n , sizeof(*symtab->symbols)); if (symtab->symbols == NULL) goto bad; // copy symbols info our symtab and enter them info the hash table for (j = 0; j < n; j++, syms++) { DBT key, value; char *sym_name = symtab->strs + syms->st_name; // skip non-object and non-function symbols int st_type = ELF_ST_TYPE(syms->st_info); if ( st_type != STT_FUNC && st_type != STT_OBJECT) continue; // skip empty strings and undefined symbols if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue; symtab->symbols[j].name = sym_name; symtab->symbols[j].offset = syms->st_value - baseaddr; symtab->symbols[j].size = syms->st_size; key.data = sym_name; key.size = strlen(sym_name) + 1; value.data = &(symtab->symbols[j]); value.size = sizeof(symtab_symbol); (*symtab->hash_table->put)(symtab->hash_table, &key, &value, 0); } } } goto quit; bad: destroy_symtab(symtab); symtab = NULL; quit: if (shbuf) free(shbuf); if (phbuf) free(phbuf); if (scn_cache) { for (cnt = 0; cnt < ehdr.e_shnum; cnt++) { if (scn_cache[cnt].c_data != NULL) { free(scn_cache[cnt].c_data); } } free(scn_cache); } return symtab; }
/* Main entry point of elf-parser */ int32_t main(int32_t argc, char *argv[]) { int32_t fd; Elf32_Ehdr eh; /* elf-header is fixed size */ if(argc!=2) { printf("Usage: elf-parser <ELF-file>\n"); return 0; } fd = open(argv[1], O_RDONLY|O_SYNC); if(fd<0) { printf("Error %d Unable to open %s\n", fd, argv[1]); return 0; } /* ELF header : at start of file */ read_elf_header(fd, &eh); if(!is_ELF(eh)) { return 0; } if(is64Bit(eh)){ Elf64_Ehdr eh64; /* elf-header is fixed size */ Elf64_Shdr* sh_tbl; /* section-header table is variable size */ read_elf_header64(fd, &eh64); print_elf_header64(eh64); /* Section header table : */ sh_tbl = malloc(eh64.e_shentsize * eh64.e_shnum); if(!sh_tbl) { printf("Failed to allocate %d bytes\n", (eh64.e_shentsize * eh64.e_shnum)); } read_section_header_table64(fd, eh64, sh_tbl); print_section_headers64(fd, eh64, sh_tbl); /* Symbol tables : * sh_tbl[i].sh_type * |`- SHT_SYMTAB * `- SHT_DYNSYM */ print_symbols64(fd, eh64, sh_tbl); /* Save .text section as text.S */ save_text_section64(fd, eh64, sh_tbl); /* Disassemble .text section * Logs asm instructions to stdout * Currently supports ARMv7 */ disassemble64(fd, eh64, sh_tbl); } else{ Elf32_Shdr* sh_tbl; /* section-header table is variable size */ print_elf_header(eh); /* Section header table : */ sh_tbl = malloc(eh.e_shentsize * eh.e_shnum); if(!sh_tbl) { printf("Failed to allocate %d bytes\n", (eh.e_shentsize * eh.e_shnum)); } read_section_header_table(fd, eh, sh_tbl); print_section_headers(fd, eh, sh_tbl); /* Symbol tables : * sh_tbl[i].sh_type * |`- SHT_SYMTAB * `- SHT_DYNSYM */ print_symbols(fd, eh, sh_tbl); /* Save .text section as text.S */ save_text_section(fd, eh, sh_tbl); /* Disassemble .text section * Logs asm instructions to stdout * Currently supports ARMv7 */ disassemble(fd, eh, sh_tbl); } return 0; }
/* exe_commande Descr: Execute les différentes opérations demandés par l'utilisateur Param: - c: Commande (voir #define ci dessus) - nomfichier: Nom du fichier à lire - nm_index: Argument de l'option -x, NULL si l'option n'a pas été choisis Return: Etat de sortie de la fonction: - -1: Impossible d'ouvrir le fichier donné - 0: Ouverture du fichier réussi */ int exe_commande(unsigned char c, char *nomfichier,char* nm_index) { if (nomfichier==NULL) return NOMFICHIERNULL; FILE *f; Elf32_Ehdr header; Elf32_Shdr *section_header_table; Elf32_Sym *symbol_tab; sectioncontent section; int nbSym = 0; int valid = 0; f = fopen(nomfichier,"r"); // Ouverture du fichier nomfichier if(f == NULL) { // Echec d'ouverture return FICHIERINEXISTANT; } else { /* Lecture Header */ header = read_header(f,&valid); if(valid==1) { // Header valide /* Lecture Table de section header */ section_header_table = read_section_header_table(f,header); /* Lecture Table des symboles */ symbol_tab = read_symbol_table(f ,section_header_table, header, &nbSym); if(c&COMMANDE_HEAD) //COMMANDE_HEAD { printf("ELF Header:\n"); print_header(header); printf("\n"); } if(c&COMMANDE_SECTIONTAB)//COMMANDE_SECTIONTAB { printf("Section Headers:\n"); print_section_header_table(f,section_header_table,header); printf("\n"); } if(c&COMMANDE_CONTENT)//COMMANDE_CONTENT { printf("Section %s content:\n", nm_index); section = read_section_content(f,nm_index, section_header_table, header); if(section.content==NULL) { printf("Warning, section : %s,was not dumped because it does not exist \n",nm_index); } else { print_section_content(section); } } if(c&COMMANDE_RELOC)//COMMANDE_RELOC { print_all_reloc_table(f, header, section_header_table, symbol_tab); printf("\n"); } if(c&COMMANDE_SYM)//COMMANDE_SYM { printf("Symbol table\n"); print_symbol_table(symbol_tab, nbSym, f, section_header_table, header); freeSymbolTable(symbol_tab); } } else // Header non valide { if(valid ==-1) { // Fichier non valid (vide ou autre) return FILEEMPTY;fprintf(stderr, "%s : Error while reading the file (possibly empty)\n",nomfichier); } else if(valid==0) { //Fichier pas au format elf32 return NOTELF32; } else { // Cas normalement impossible fprintf(stderr, "Impossible error append\n"); } } fclose(f); // Fermeture du fichier } return 0; }