Example #1
0
// 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;
}