// 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; }
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; }