/** * @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, §ion_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 ); }
/** * @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, §ion_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 ); }
/** * @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, §ion_tab); if (symtab_libc!=NULL && fp_libc!=NULL) elf_load_scntab(fp_libc ,32, §ion_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 ); }