//-------------------------------------------------------------------------------- static int convElfToMiniFile(char* elffilename, char* melffilename) { int fdelf, fdmelf, modhdrsymndx; Elf* elf; Elf32_Ehdr *ehdr; Elf_Scn *relatextscn, *textscn, *symtabscn, *strtabscn; Melf_Scn *m_relatextscn, *m_textscn, *m_symtabscn; Melf* melf; symbol_map_t* symmap; Melf_Data *relatextdata, *symtabdata, *textdata; symbol_map_t symmap_storage; printf("ELF File: %s\n", elffilename); printf("Mini-ELF File: %s\n", melffilename); symmap = &symmap_storage; // Open ELF file for reading if ((fdelf = open(elffilename, O_RDONLY)) < 0){ fprintf(stderr, "%s: ", elffilename); perror("convElfToMini -> fopen: "); exit(EXIT_FAILURE); } // Open Mini-ELF file for writing if ((fdmelf = open(melffilename, (O_RDWR | O_CREAT | O_EXCL), (S_IRWXU | S_IRWXG | S_IRWXO))) < 0){ fprintf(stderr, "%s: ", melffilename); perror("convElfToMini -> fopen: "); exit(EXIT_FAILURE); } // Check version of ELF Library if (elf_version(EV_CURRENT) == EV_NONE){ fprintf(stderr, "Library version is out of date.\n"); exit(EXIT_FAILURE); } // Get the ELF descriptor elf = elf_begin(fdelf, ELF_C_READ, NULL); if (NULL == elf){ fprintf(stderr, "elf_begin: Error getting elf descriptor\n"); exit(EXIT_FAILURE); } // Ensure that it is an ELF format file if (elf_kind(elf) != ELF_K_ELF){ fprintf(stderr, "This program can only read ELF format files.\n"); exit(EXIT_FAILURE); } // Get the ELF Header ehdr = elf32_getehdr(elf); if (NULL == ehdr){ fprintf(stderr, "Error reading ELF header\n"); exit(EXIT_FAILURE); } // Verify if the ELF is AVR specific if (ehdr->e_machine != EM_AVR && ehdr->e_machine != EM_MSP430){ fprintf(stderr, "This ELF binary is not supported.\n"); exit(EXIT_FAILURE); } e_machine = ehdr->e_machine; // Create a new Mini-ELF (MELF) descriptor if ((melf = melf_new(fdmelf)) == NULL){ fprintf(stderr, "Error creating a new MELF descriptor\n"); exit(EXIT_FAILURE); } // Get the pointer to .symtab section if ((symtabscn = getELFSectionByName(elf, ".symtab")) == NULL){ fprintf(stderr, "Error getting .symtab section.\n"); exit(EXIT_FAILURE); } // Get the pointer to .rela.text section /* if ((relatextscn = getELFSectionByName(elf, ".rela.text")) == NULL){ fprintf(stderr, "Error getting .rela.text section.\n"); exit(EXIT_FAILURE); } */ relatextscn = getELFSectionByName(elf, ".rela.text"); // Get the pointer to .text section if ((textscn = getELFSectionByName(elf, ".text")) == NULL){ fprintf(stderr, "Error getting .text section.\n"); exit(EXIT_FAILURE); } if ((strtabscn = getELFSectionByName(elf, ".strtab")) == NULL ) { fprintf(stderr, "Error getting .strtab section. \n"); exit(EXIT_FAILURE); } // DEBUG info. to verify we have the correct sections DEBUG("Section Number (.text): %d\n", (int)elf_ndxscn(textscn)); if( relatextscn != NULL ) { DEBUG("Section Number (.rela.text): %d\n", (int)elf_ndxscn(relatextscn)); } DEBUG("Section Number (.symtab): %d\n", (int)elf_ndxscn(symtabscn)); // Initialize Symbol Map if (initSymbolMap(symmap, symtabscn) < 0){ fprintf(stderr, "Error initializing symbol map.\n"); exit(EXIT_FAILURE); } // // Set string table to symbol map // addStrTabToSymbolMap( symmap, strtabscn ); addTxtScnToSymbolMap( symmap, textscn ); // Convert Relocation Table // Simon: convert relocation before text section // because some symbols will be patched in .text section if( relatextscn != NULL ) { if ((relatextdata = convRelaScn(relatextscn, symmap)) == NULL){ fprintf(stderr, "Error converting Rela table.\n"); exit(EXIT_FAILURE); } } // Convert Text Section if ((textdata = convProgbitsScn(textscn)) == NULL){ fprintf(stderr, "Error converting text section.\n"); exit(EXIT_FAILURE); } // Add mod_header symbol if ((modhdrsymndx = getELFSymbolTableNdx(elf, "mod_header")) == -1){ fprintf(stderr, "Could not locate symbol: mod_header. Not a valid SOS module\n"); exit(EXIT_FAILURE); } addMelfSymbol(symmap, modhdrsymndx); melf_setModHdrSymNdx(melf, symmap->etommap[modhdrsymndx]); // Convert Symbol Table if ((symtabdata = convSymScn(symmap)) == NULL){ fprintf(stderr, "Error convering symbol table.\n"); exit(EXIT_FAILURE); } // Create a new MELF Symbol table section if ((m_symtabscn = melf_new_scn(melf)) == NULL){ fprintf(stderr, "Error creating symbol table MELF section.\n"); exit(EXIT_FAILURE); } convElfHdr(m_symtabscn, symtabscn); melf_add_data_to_scn(m_symtabscn, symtabdata); // Create a new MELF Relocation table section if( relatextscn != NULL ) { if ((m_relatextscn = melf_new_scn(melf)) == NULL){ fprintf(stderr, "Error creating relocation table MELF section.\n"); exit(EXIT_FAILURE); } convElfHdr(m_relatextscn, relatextscn); melf_add_data_to_scn(m_relatextscn, relatextdata); } // Create a new MELF Symbol table section if ((m_textscn = melf_new_scn(melf)) == NULL){ fprintf(stderr, "Error creating .text MELF section.\n"); exit(EXIT_FAILURE); } convElfHdr(m_textscn, textscn); melf_add_data_to_scn(m_textscn, textdata); // Sort the MELF Sections (Enable single pass writing on the nodes) melf_sortScn(melf); // Set the section offsets melf_setScnOffsets(melf); // Write the MELF File melf_write(melf); #ifdef DBGMODE prettyPrintMELF(melf); #endif // Close ELF Descriptor elf_end(elf); // Close ELF File close(fdelf); // Close MELF File close(fdmelf); return 0; }
//------------------------------------------------------------------- static void avr_create_new_symbol_table(Elf_Data* nedata, Elf* elf, Elf* nelf, Elf32_Shdr *nshdr, uint32_t startaddr, bblklist_t* blist) { Elf32_Ehdr* ehdr; Elf32_Sym* nsym; Elf_Data* nreladata; Elf32_Rela *nerela; int numSyms, numRecs, i, txtscnndx, btxtscnfound; Elf_Scn *txtscn, *nrelascn; Elf32_Shdr *txtshdr, *nrelashdr; DEBUG("Determine .text section index ...\n"); // Get the ELF Header if ((ehdr = elf32_getehdr(elf)) == NULL){ fprintf(stderr, "avr_create_new_symbol_table: Error reading ELF header\n"); exit(EXIT_FAILURE); } txtscn = NULL; txtscnndx = 1; btxtscnfound = 0; while ((txtscn = elf_nextscn(elf, txtscn)) != NULL){ if ((txtshdr = elf32_getshdr(txtscn)) != NULL){ char* CurrSecName = NULL; CurrSecName = elf_strptr(elf, ehdr->e_shstrndx, txtshdr->sh_name); if (strcmp(CurrSecName, ".text") == 0){ btxtscnfound = 1; break; } } txtscnndx++; } if (0 == btxtscnfound){ fprintf(stderr, "avr_create_new_symbol_table: Cannot find .text section.\n"); exit(EXIT_FAILURE); } DEBUG(".text section index: %d\n", txtscnndx); // Get .rela.text section nrelascn = getELFSectionByName(nelf, ".rela.text"); nrelashdr = elf32_getshdr(nrelascn); nreladata = NULL; nreladata = elf_getdata(nrelascn, nreladata); numRecs = nreladata->d_size/nrelashdr->sh_entsize; numSyms = nedata->d_size/nshdr->sh_entsize; nsym = (Elf32_Sym*)(nedata->d_buf); for (i = 0; i < numSyms; i++){ if ((nsym->st_shndx == txtscnndx) && (ELF32_ST_TYPE(nsym->st_info) != STT_SECTION)){ if (nsym->st_value > startaddr){ uint32_t oldValue = nsym->st_value; nsym->st_value = find_updated_address(blist, oldValue); // Check if we have to further modify this symbol (if it is used as a call target value) int j; nerela = (Elf32_Rela*)nreladata->d_buf; for (j = 0; j < numRecs; j++){ if ((ELF32_R_SYM(nerela->r_info) == i) && ((ELF32_R_TYPE(nerela->r_info) == R_AVR_CALL)|| (ELF32_R_TYPE(nerela->r_info) == R_AVR_13_PCREL))){ // Check if it is indeed a call instruction before changing the symbol avr_instr_t instr; instr = find_instr_at_new_addr(blist, nerela->r_offset); if (((instr.rawVal & OP_TYPE10_MASK) == OP_CALL) || ((instr.rawVal & OP_TYPE17_MASK) == OP_RCALL)){ nsym->st_value -= sizeof(avr_instr_t) * 2; DEBUG("Call target symbol. Modify to accomodate safe stack store.\n"); } else DEBUG("Jmp target symbol. No modification to symbol required.\n"); break; } // Follwing is only for producing a more readable elf.lst if ((ELF32_ST_BIND(nsym->st_info) == STB_LOCAL) && (ELF32_ST_TYPE(nsym->st_info) == STT_FUNC) && ((ELF32_R_TYPE(nerela->r_info) == R_AVR_CALL) || (ELF32_R_TYPE(nerela->r_info) == R_AVR_13_PCREL)) && (nerela->r_addend == (nsym->st_value - (2*sizeof(avr_instr_t))))){ nsym->st_value -= sizeof(avr_instr_t) * 2; DEBUG("Call target symbol. Modified for ELF pretty print.\n"); } nerela++; } DEBUG("Entry: %d Old Value: 0x%x New Value: 0x%x\n", i, (int)oldValue, (int)nsym->st_value); } } nsym++; } return; }