Ejemplo n.º 1
0
// fonction permettant d'extraire une section du fichier ELF et de la chargée dans le segment du même nom
// parametres :
//   fp         : le pointeur du fichier ELF
//   memory     : la structure de mémoire virtuelle
//   scn        : le nom de la section à charger
//   permission : l'entier représentant les droits de lecture/ecriture/execution
//   add_start  : l'addresse virtuelle à laquelle la section doit être chargée
//
// retourne 0 en cas de succes, une valeur non nulle sinon
int elf_load_section_in_memory(FILE* fp, mem memory, char* scn,unsigned int permissions,unsigned long long add_start) 
{
    byte *ehdr    = __elf_get_ehdr( fp );
    byte *content = NULL;
    uint  textsz  = 0;
    vsize sz;
    vaddr addr;

    byte *useless = elf_extract_section_header_table( ehdr, fp );
    free( useless );

    if ( NULL == ehdr ) 
    {
        WARNING_MSG( "Can't read ELF file" );
        return 1;
    }

    if ( 1 == attach_scn_to_mem(memory, scn, SCN_ATTR( WIDTH_FROM_EHDR( ehdr ), permissions ) ) ) 
    {
        WARNING_MSG( "Unable to create %s section", scn );
        free( ehdr );
        return 1;
    }

    content = elf_extract_scn_by_name( ehdr, fp, scn, &textsz, NULL );
    if ( NULL == content ) {
        WARNING_MSG( "Corrupted ELF file" );
        free( ehdr );
        return 1;
    }

    switch( WIDTH_FROM_EHDR(ehdr) ) {
    case 32 :
        sz._32   = textsz/*+8*/; /* +8: In case adding a final sys_exit is needed */
        addr._32 = add_start;
        break;
    case 64 :
        sz._64   = textsz/*+8*/; /* +8: In case adding a final sys_exit is needed */
        addr._64 = add_start;
        break;
    default :
        WARNING_MSG( "Wrong machine width" );
        return 1;
    }

    if ( 1 == fill_mem_scn(memory, scn, sz, addr, content ) ) {
        free( ehdr );
        free( content );
        WARNING_MSG( "Unable to fill in %s segment", scn );
        return 1;
    }

    free( content );
    free( ehdr );

    return 0;
}
Ejemplo n.º 2
0
/**
 * @param fp le fichier elf original
 * @param seg le segment à reloger
 * @param mem l'ensemble des segments
 *
 * @brief Cette fonction effectue la relocation du segment passé en parametres
 * @brief l'ensemble des segments doit déjà avoir été chargé en memoire.
 *
 * VOUS DEVEZ COMPLETER CETTE FONCTION POUR METTRE EN OEUVRE LA RELOCATION !!
 */
void reloc_segment(FILE* fp, segment seg, mem memory,unsigned int endianness,stab symtab) 
{
    byte *ehdr    = __elf_get_ehdr( fp );
    uint32_t  scnsz  = 0;
    Elf32_Rel *rel = NULL;
    char* reloc_name = malloc(strlen(seg.name)+strlen(RELOC_PREFIX_STR)+1);
    scntab section_tab;

    // on recompose le nom de la section
    memcpy(reloc_name,RELOC_PREFIX_STR,strlen(RELOC_PREFIX_STR)+1);
    strcat(reloc_name,seg.name);

    // on récupere le tableau de relocation et la table des sections
    rel = (Elf32_Rel *)elf_extract_scn_by_name( ehdr, fp, reloc_name, &scnsz, NULL );
    elf_load_scntab(fp ,32, &section_tab);



    if (rel != NULL && seg.content!=NULL && seg.size._32!=0) {

        INFO_MSG("--------------Relocation de %s-------------------\n",seg.name) ;
        INFO_MSG("Nombre de symboles a reloger: %ld\n",scnsz/sizeof(*rel)) ;


        //------------------------------------------------------

        //TODO : faire la relocation ICI !

        //------------------------------------------------------

    }
    del_scntab(section_tab);
    free( rel );
    free( reloc_name );
    free( ehdr );

}
Ejemplo n.º 3
0
/**
 * @param fp le fichier elf original
 * @param seg le segment à reloger
 * @param mem l'ensemble des segments
 * @param endianness le boutisme du programme
 * @param symtab la table des symbole du programme
 *
 * @brief Cette fonction effectue la relocation du segment passé en parametres
 * @brief l'ensemble des segments doit déjà avoir été chargé en memoire.
 *
 */
void reloc_segment(FILE* fp, segment seg, char* segname, memory mem, unsigned int endianness,stab* symtab) {
  byte *ehdr    = __elf_get_ehdr(fp);
  uint32_t  scnsz  = 0;
  Elf32_Rel *rel = NULL;
  char* reloc_name = malloc(strlen(segname)+strlen(RELOC_PREFIX_STR)+1);
  scntab section_tab;

  // on recompose le nom de la section
  memcpy(reloc_name,RELOC_PREFIX_STR,strlen(RELOC_PREFIX_STR)+1);
  strcat(reloc_name,segname);

  // on récupere le tableau de relocation et la table des sections
  rel = (Elf32_Rel *)elf_extract_scn_by_name( ehdr, fp, reloc_name, &scnsz, NULL );
  elf_load_scntab(fp ,32, &section_tab);

  if (rel != NULL && seg.raddr!=NULL && seg.size !=0) {

      INFO_MSG("--------------Relocation de %s-------------------\n",segname) ;
      INFO_MSG("Nombre de symboles a reloger: %ld\n",scnsz/sizeof(*rel)) ;

      int i = 0, j = 0;
      unsigned int V = 0;
      unsigned int S = 0;
      unsigned int A = 0;
      unsigned int T = 0;
      
      for (i=0; i<scnsz/sizeof(*rel); i++) {
          T =0;
          __Elf_Rel_flip_endianness((byte *)(rel+i), 32, endianness);
          unsigned int offset = rel[i].r_offset; // decalage par rapport au debut de section
          int sym = (int) ELF32_R_SYM(rel[i].r_info);
          int type = (unsigned char) ELF32_R_TYPE(rel[i].r_info);
	  int P = seg.vaddr + offset;

          DEBUG_MSG("Entrée de relocation : offset %08x info =%08x sym = %08x type =%08x\n",rel[i].r_offset,rel[i].r_info,sym,type);
          DEBUG_MSG("Symbole en fonction duquel on reloge : symbole %s de type %d\n",symtab->sym[sym].name, type);

          if (symtab->sym[sym].type==STT_SECTION) {
            S = symtab->sym[sym].addr._32;
 
	    if (type == R_ARM_ABS8) {
              uint8_t oct = read_memory_value(P, mem);
              if (oct < 0)
                A = oct | 0xFFFFFF00;
              else
                A = oct;
              V = A + S;
              write_memory_value(P, V, mem);  
              printf("A: %d, P: %d, S: %d, T: %d, V:%x\n", A, P, S, T, V);
            }
            
            if (type == R_ARM_ABS32) {
              A = read_word(P, mem) ;
              V = (S + A) | T;
              printf("A: %d, P: %d, S: %d, T: %d, V:%x\n", A, P, S, T, V);
              write_word(P, V, mem);
            }

            if (type == R_ARM_THM_CALL) {
            }
                         
          } 
          
          else if (symtab->sym[sym].type==STT_FUNC) {
          
            T = 1;
            S = symtab->sym[sym].addr._32;   

	    if (type == R_ARM_ABS8) {
              A = read_memory_value(P, mem) ;
              V = A + S;
              printf("A: %d, P: %d, S: %d, T: %d, V:%x\n", A, P, S, T, V);
              write_memory_value(P, V, mem);  
            }
            
            if (type == R_ARM_ABS32) {
              A = read_word(P, mem) << 1;
              V = (S + A) | T;
              printf("A: %d, P: %d, S: %d, T: %d, V:%x\n", A, P, S, T, V);
              write_word(P, V, mem);
            }

            if (type == R_ARM_THM_CALL) {
            }               
          } 

          else if (symtab->sym[sym].type==STT_NOTYPE) {
          
            S = symtab->sym[sym].addr._32;   

	    if (type == R_ARM_ABS8) {
              A = read_memory_value(P, mem);
              V = A + S;
              printf("A: %d, P: %d, S: %d, T: %d, V:%x\n", A, P, S, T, V);
              write_memory_value(P, V, mem);  
            }
            
            if (type == R_ARM_ABS32) {
              A = read_word(P, mem);
              V = (S + A) | T;
              printf("A: %d, P: %d, S: %d, T: %d, V:%x\n", A, P, S, T, V);
              write_word(P, V, mem);
            }

            if (type == R_ARM_THM_CALL) {
            }               
          }  
       
          else {
              WARNING_MSG("%d non traité pour l'instant",symtab->sym[sym].type) ;
              continue;
          }
      }
  }
  del_scntab(section_tab);
  free( rel );
  free( reloc_name );
  free( ehdr );
}
Ejemplo n.º 4
0
/**
 * @param fp le fichier elf original
 * @param seg le segment a reloger
 * @param mem l'ensemble des segments
 * @param endianness le boutisme du programme
 * @param symtab la table des symbole du programme
 * @param symtab_libc la table des symbole de la libc (NULL si inutile)
 * @param fp_libc le fichier elf de la libc (NULL si inutile)
 * @brief Cette fonction effectue la relocation du segment passe en parametres
 * @brief l'ensemble des segments doit deja avoir ete charge en memoire.
 *
 * VOUS DEVEZ COMPLETER CETTE FONCTION POUR METTRE EN OEUVRE LA RELOCATION !!
 */
void reloc_segment(FILE* fp, segment seg, mem memory,unsigned int endianness,stab* symtable,stab* symtab_libc,FILE* fp_libc) {
    byte *ehdr    = __elf_get_ehdr( fp );
    uint32_t  scnsz  = 0;
    Elf32_Rel *rel = NULL;
    char* reloc_name = malloc(strlen(seg.name)+strlen(RELOC_PREFIX_STR)+1);
    scntab section_tab;
    scntab section_tab_libc;

    // on recompose le nom de la section
    memcpy(reloc_name,RELOC_PREFIX_STR,strlen(RELOC_PREFIX_STR)+1);
    strcat(reloc_name,seg.name);

    // on recupere le tableau de relocation et la table des sections
    rel = (Elf32_Rel *)elf_extract_scn_by_name( ehdr, fp, reloc_name, &scnsz, NULL );
    elf_load_scntab(fp ,32, &section_tab);

    if (symtab_libc!=NULL && fp_libc!=NULL)
        elf_load_scntab(fp_libc ,32, &section_tab_libc);


    if (rel != NULL &&seg.content!=NULL && seg.size._32!=0) {
        if(verbose>0) {
            INFO_MSG("--------------Relocation of %s-------------------\n",seg.name) ;
            INFO_MSG("Number of symbol to relocate: %ld\n",scnsz/sizeof(*rel)) ;
        }

        //------------------------------------------------------

        int i=0;
        uint sym;
        uint type;
        uint info;
        uint offset;
        //display :
        if(verbose>0) {
            //printf("scnsz=%d\n", scnsz);
            //print_scntab(section_tab);
            printf("Offset    Info      Type            Sym.Value  Sym.Name\n");
            while(i<scnsz/sizeof(*rel)) {
                info=rel[i].r_info;
                offset=rel[i].r_offset;
                FLIP_ENDIANNESS(info) ;
                FLIP_ENDIANNESS(offset) ;
                sym=ELF32_R_SYM(info);
                type=ELF32_R_TYPE(info);
                if (type>32) {
                    WARNING_MSG("Unknown type : %d",type);
                }
                else {
                    printf("%08X  %08X  %-14s  %08X   %s\n",offset,info,MIPS32_REL[type],sym,(*symtable).sym[sym].name);
                    i++;
                }

            }
        }
        i=0;
        //------------------------------------------------------
        //Reloc :
        int A,V,P;
        //int segnum;
        uint32_t S;
        while(i<scnsz/sizeof(*rel)) {
            info=rel[i].r_info;
            offset=rel[i].r_offset;
            FLIP_ENDIANNESS(info) ;
            FLIP_ENDIANNESS(offset) ;
            sym=ELF32_R_SYM(info);
            type=ELF32_R_TYPE(info);
            //printf("Relocating symbol %d\n",i );
            //segnum=seg_from_scnidx((*symtable).sym[sym].scnidx,(*symtable),memory);
            //if(segnum==-1){
            //    WARNING_MSG("Couldn't resolve scndix correspondance");
            //    break;
            //}
            //S=memory->seg[segnum].start._32+(*symtable).sym[sym].addr._32;//a verif
            //printf("sym=%d, symbtable size=%d\n", sym,(*symtable).size);
            if(addr_from_symnb(sym, (*symtable), memory,&S)==-1) {
                WARNING_MSG("Trying to resolve scndix correspondance in libcsymtab");
            }

            P=seg.start._32+offset;
            memRead(P,1,&A);
            //printf("Relocation type %s\n",MIPS32_REL[type] );
            switch (type) {
            case 2:
                V=S+A;

                //printf("V= %X,S=%X,A=%X,P=%X\n",V,S,A,P);
                memWrite(P,1,V);
                break;
            case 4:
                V=(A&0xFC00000)|((((A<<2)|((P&0xF0000000)+S))>>2)&0x3FFFFFF);

                //printf("V= %X,S=%X,A=%X,P=%X\n",V,S,A,P);
                memWrite(P,1,V);
                break;
            case 5:
                ;
                uint nexttype=rel[i+1].r_info;
                uint nextoffset=rel[i+1].r_offset;
                FLIP_ENDIANNESS(nexttype);
                FLIP_ENDIANNESS(nextoffset);
                nexttype=ELF32_R_TYPE(nexttype);
                if(nexttype!=6) {
                    WARNING_MSG("R_MIPS_HI16 not followed by R_MIIPS_LO16 : %s",MIPS32_REL[nexttype]);
                }
                else {

                    int P2=seg.start._32+nextoffset,A2;
                    memRead(P2,1,&A2);
                    int AHL;
                    AHL=(A<<16)+(short)(A2);
                    //printf("A2=%X short A2=%X\n",A2, (short)A2 );
                    //printf("AHL : %X\n",AHL );
                    //printf("Total=%X AHL+S=%X, (AHL+S)&0xFFFF=%X, diff=%X\n",((AHL+S-(short)(AHL+S))>>16),AHL+S,(AHL+S)&0xFFFF,AHL+S-(short)AHL+S) ;
                    V=(A & 0xFFFF0000)|(  ((AHL+S-(short)(AHL+S))>>16)   &0xFFFF);

                    //printf("V= %X,S=%X,A=%X,A2=%X,P=%X,P2=%X, AHL=%X\n",V,S,A,A2,P,P2,AHL);
                    memWrite(P,1,V);
                }
                break;
            case 6:
                ;
                int previoustype=rel[i-1].r_info;
                int previousoffset=rel[i-1].r_offset;
                FLIP_ENDIANNESS(previoustype);
                FLIP_ENDIANNESS(previousoffset);
                previoustype=ELF32_R_TYPE(previoustype);
                if(previoustype!=5) {
                    WARNING_MSG("R_MIPS_LO16 not preceded by R_MIPS_HI16 : %s",MIPS32_REL[previoustype]);
                }
                else {

                    int32_t P2=seg.start._32+previousoffset,A2;
                    memRead(P2,1,&A2);
                    int32_t AHL=(A2<<16)+(short)(A);
                    V=(A&0xFFFF0000)|((short)(AHL+S)&0xFFFF);

                    //printf("V= %X,S=%X,A=%X,P=%X\n",V,S,A,P);
                    memWrite(P,1,V);
                }
                break;
            default:
                if (type>32) {
                    WARNING_MSG("Unknown type : %d, relocation impossible for element %d",type,i);
                }
                else {
                    WARNING_MSG("Unknown type : %s(code : %d), relocation impossible for element %d",MIPS32_REL[type],type,i);
                }
                break;
            }
            i++;
        }
        //------------------------------------------------------

    }
    del_scntab(section_tab);
    free( rel );
    free( reloc_name );
    free( ehdr );

}