Example #1
0
//--------------------------------------------------------------------------------
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;
}
Example #2
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;
}