Ejemplo n.º 1
0
// la fonction charge un fichier elf en entrée en utilisant
// les arguments du prototype de la fonction main (cf. fiches infos)
//
mem load(char* name) 
{
    char* section_names[NB_SECTIONS]= {TEXT_SECTION_STR,RODATA_SECTION_STR,DATA_SECTION_STR,BSS_SECTION_STR}; 	/* 4 sections dont les noms ont été définie ci-dessus */ 
    unsigned int segment_permissions[NB_SECTIONS]= {R_X,R__,RW_,RW_};						/* décrit les différentes permissions possibles */ 
    unsigned int nsegments;		/* nombre de segment de mémoire */ 
    int i=0,j=0;
    unsigned int type_machine;
    unsigned int endianness;   //little ou big endian
    unsigned int bus_width;    // 32 bits ou 64bits
    unsigned int next_segment_start = START_MEM; // compteur pour designer le début de la prochaine section

    mem memory;  // memoire virtuelle, c'est elle qui contiendra toute les données du programme
    stab symtab= new_stab(0); // table des symboles
    FILE * pf_elf;


    if ((pf_elf = fopen(name,"r")) == NULL) { /* si le fichier ne s'ouvre pas, on affiche un message erreur */
        ERROR_MSG("cannot open file %s", name);
    }

    if (!assert_elf_file(pf_elf)) /* si le fichier ne peut être lu, on affiche un message erreur */
        ERROR_MSG("file %s is not an ELF file", name);


    // recuperation des info de l'architecture
    elf_get_arch_info(pf_elf, &type_machine, &endianness, &bus_width);
    // et des symboles
    elf_load_symtab(pf_elf, bus_width, endianness, &symtab);


    nsegments = get_nsegments(symtab,section_names,NB_SECTIONS); /* ici, nsegments passe à 4 */

    // allouer la memoire virtuelle
    memory=init_mem(nsegments+4); /* nsegments incrémenté pour prévoir la pile, [heap], [lib] et [vssyscall] */

    // Ne pas oublier d'allouer les differentes sections
    j=0;
    for (i=0; i<NB_SECTIONS; i++) {
        if (is_in_symbols(section_names[i],symtab)) {
            elf_load_section_in_memory(pf_elf,memory, section_names[i],segment_permissions[i],next_segment_start);
            next_segment_start+= ((memory->seg[j].size._32+0x1000)>>12 )<<12; // on arrondit au 1k suppérieur
//          print_segment_raw_content(&memory->seg[j]); /* affiche le contenu initial du segment */ 
            j++;
        }
    }


/* alloue le segment [heap] qui restera vide */
    memory->seg[j].name          = strdup("[heap]");     /* nom du segment */
    memory->seg[j].size._32      = 0xff7f8000;    /* le segment est initialement vide */ 
    memory->seg[j].start._32     = 0x5000;      /* adresse de départ du segment */
    memory->seg[j].attr          = SCN_ATTR(1, R__);         // permission sur le segment 
    memory->seg[j].content       = calloc(memory->seg[j].size._32, sizeof(char)); //start ?    /* on alloue la mémoire réelle utile pour ce segment */

/* alloue le segment [lib] */
    memory->seg[j+1].name          = strdup("[lib]");     /* nom du segment */
    memory->seg[j+1].size._32      = 0x2000;   /* le segment est initialement vide */ 
    memory->seg[j+1].start._32     = 0xff7fd000;      /* adresse de départ du segment */
    memory->seg[j+1].attr          = SCN_ATTR(1, R__);         /* permission sur le segment */   
    memory->seg[j+1].content       = calloc(memory->seg[j+1].size._32, sizeof(char));    /* on alloue la mémoire réelle utile pour ce segment */

/* alloue la pile */
    memory->seg[j+2].name        = strdup("[stack]");   /* nom du segment */
    memory->seg[j+2].size._32    = 0x800000;     /* le segment est initialement vide */
    memory->seg[j+2].start._32   = 0xff7ff000;  /* adresse de départ du segment */
    memory->seg[j+2].attr        = SCN_ATTR(1, RW_);         /* permission sur le segment */
    memory->seg[j+2].content     = calloc(memory->seg[j+2].size._32, sizeof(char)); /* on alloue la mémoire réelle utile pour ce segment */

/* alloue le segment pour les appels systemes */
    memory->seg[j+3].name        = strdup("[vsyscall]");/* nom du segment */
    memory->seg[j+3].size._32    = 0xfff;   /* taille du segment */ 
    memory->seg[j+3].start._32   = 0xfffff000;  /* adresse de départ du segment */
    memory->seg[j+3].attr        = SCN_ATTR(1, R_X);         /* permission sur le segment */
    memory->seg[j+3].content     = calloc(memory->seg[j+3].size._32, sizeof(char));    /* on alloue la mémoire réelle utile pour ce segment */

    printf("\n------ Fichier ELF \"%s\" : sections lues lors du chargement ------\n", name);
    print_mem(memory); /* affiche le contenu de la mémoire */ 
    stab32_print( symtab);	/* affiche les symboles contenus dans le tableau symtab */ 

    // on fait le ménage avant de partir
    //del_stab(symtab);
    fclose(pf_elf);
    puts("");
    return memory;
}
Ejemplo n.º 2
0
int loadELF (char* name,int mode,uint32_t addr) {
    if(mode==1) {
        //printf("loading at adress :");
        textStart = addr;
        //printf("%X\n", textStart);
    }
    else {
        textStart=DEFAULT_S_ADDR;
    }
    if(textStart%0x1000>0) {
        textStart = textStart+0x1000-textStart%0x1000;
    }


    char* section_names[NB_SECTIONS]= {TEXT_SECTION_STR,RODATA_SECTION_STR,DATA_SECTION_STR,BSS_SECTION_STR};
    unsigned int segment_permissions[NB_SECTIONS]= {R_X,R__,RW_,RW_};
    unsigned int nsegments;
    int i=0,j=0;
    unsigned int type_machine;
    unsigned int endianness;   //little ou big endian
    unsigned int bus_width;    // 32 bits ou 64bits
    unsigned int next_segment_start = textStart; // compteur pour designer le debut de la prochaine section

    symtab=new_stab(0);
    stab symtab_libc= new_stab(0); // table des symboles de la libc
    FILE * pf_elf, *pf_libc;


    if ((pf_elf = fopen(name,"r")) == NULL) {
        WARNING_MSG("cannot open file '%s'", name);
        return -1;
    }

    if (!assert_elf_file(pf_elf)) {
        WARNING_MSG("file %s is not an ELF file", name);
        return -1;
    }


    if ((pf_libc = fopen(PATH_TO_LIBC,"r")) == NULL) {
        ERROR_MSG("cannot open file %s", PATH_TO_LIBC);
    }

    if (!assert_elf_file(pf_libc))
        ERROR_MSG("file %s is not an ELF file", PATH_TO_LIBC);

    // recuperation des info de l'architecture
    elf_get_arch_info(pf_elf, &type_machine, &endianness, &bus_width);
    // et des symboles
    elf_load_symtab(pf_elf, bus_width, endianness, &symtab);
    elf_load_symtab(pf_libc, bus_width, endianness, &symtab_libc);
    elf_load_symtab(pf_libc, bus_width, endianness, &libcsymtab);


    nsegments = get_nsegments(symtab,section_names,NB_SECTIONS);
    nsegments += get_nsegments(symtab_libc,section_names,NB_SECTIONS);
    // allouer la memoire virtuelle
    memory=init_mem(nsegments);


    next_segment_start = LIBC_MEM_END;
    //printf("\ndebut : %08x\n",next_segment_start);
    j=0;

    // on alloue libc
    for (i=0; i<NB_SECTIONS; i++) {
        if (is_in_symbols(section_names[i],symtab_libc)) {
            elf_load_section_in_memory(pf_libc,memory, section_names[i],segment_permissions[i],next_segment_start);
            next_segment_start-= ((memory->seg[j].size._32+0x1000)>>12 )<<12; // on arrondit au 1k supp�rieur
            memory->seg[j].start._32 = next_segment_start;
//            print_segment_raw_content(&memory->seg[j]);
            j++;
        }
    }
    if(verbose>0) {
        INFO_MSG("--------------Relocation of %s-------------------",PATH_TO_LIBC);
    }
    for (i=0; i<j; i++) {
        reloc_segment(pf_libc, memory->seg[i], memory,endianness,&symtab_libc,NULL,NULL);
    }

    // on change le nom des differents segments de libc
    for (i=0; i<j; i++) {
        char seg_name [256]= {0};
        strcpy(seg_name,"libc");
        strcat(seg_name,memory->seg[i].name);
        free(memory->seg[i].name);
        memory->seg[i].name=strdup(seg_name);
    }


    // On va chercher les sections du fichier
    int k =j;
    next_segment_start = textStart;




    for (i=0; i<NB_SECTIONS; i++) {
        if (is_in_symbols(section_names[i],symtab)) {
            elf_load_section_in_memory(pf_elf,memory, section_names[i],segment_permissions[i],next_segment_start);
            next_segment_start+= ((memory->seg[j].size._32+0x1000)>>12 )<<12; // on arrondit au 1k supperieur
//            print_segment_raw_content(&memory->seg[j]);
            j++;
        }
    }

    // on reloge chaque section du fichier
    if(verbose>0) {
        INFO_MSG("--------------Relocation of %s-------------------",name);
    }
    for (i=k; i<j; i++) {
        reloc_segment(pf_elf, memory->seg[i], memory,endianness,&symtab,&symtab_libc,pf_libc);
    }
    //TODO allouer la pile (et donc modifier le nb de segments)

    // printf("\n------ Fichier ELF \"%s\" : sections lues lors du chargement ------\n", name) ;
    // print_mem(memory);
    //stab32_print( symtab);
    //stab32_print( symtab_libc);
    // on fait le menage avant de partir
    //del_mem(memory);
    //del_stab(symtab_libc);
    //del_stab(symtab);

    //Recuperation des bornes des segments rx
    for (k = 0; k < memory->nseg; k++) {
        if(strcmp(memory->seg[k].name,".text")==0) {
            textStart=memory->seg[k].start._32;
            textEnd=memory->seg[k].start._32+memory->seg[k].size._32;
        }
        if(strcmp(memory->seg[k].name,"libc.text")==0) {
            libcTextStart=memory->seg[k].start._32;
            libcTextEnd=memory->seg[k].start._32+memory->seg[k].size._32;
        }
    }
    if(verbose>0)INFO_MSG("R_X segments: %8.8X-%8.8X and %8.8X-%8.8X",textStart,textEnd,libcTextStart,libcTextEnd );


    //Initialisation de l'emulateur en vu d'un run
    initprog();



    INFO_MSG("File loaded :'%s'",name);
    fclose(pf_elf);
    fclose(pf_libc);
    //puts("");
    return 0;
}