Esempio n. 1
0
  char * version_needed::lookup_version(Elf32_Half ver)
  {
    current_entry = reinterpret_cast<Elf32_Verneed *>(ver_needed);
    
    while(current_entry != NULL)
      {
	if (current_entry->vn_aux == 0)
	  current_aux_entry = NULL;
	else
	  current_aux_entry = reinterpret_cast<Elf32_Vernaux *>(reinterpret_cast<char *>(current_entry) + 
                                                                convert_endian(4, current_entry->vn_aux, match_endian));
	while (current_aux_entry != NULL)
	  {
	    if (get_cur_other() == ver) /* found! */
	      return get_cur_vername();
	    if (current_aux_entry->vna_next == 0)
	      current_aux_entry = NULL;
	    else
	      current_aux_entry = reinterpret_cast<Elf32_Vernaux *>(reinterpret_cast<char *>(current_aux_entry) +
								    convert_endian(4, current_aux_entry->vna_next, match_endian));
	  }
	
	if (current_entry->vn_next == 0)
	  current_entry = NULL;
	else
	  current_entry = reinterpret_cast<Elf32_Verneed *>(reinterpret_cast<char *>(current_entry) + 
							    convert_endian(4, current_entry->vn_next, match_endian));
      }
    return NULL;
  }
Esempio n. 2
0
void		write_ld_first(char *args, t_size *p, int fd, t_lab *lab)
{
  short int	ind;
  int		direct;

  if (args[0] == '%' && args[1] != ':')
    {
      args++;
      direct = my_getnbr(args);
      convert_endian(&direct, my_endian());
      p->len += write(fd, &direct, sizeof(int));
    }
  else if (args[0] != '%')
    {
      ind = my_getnbr(args);
      convert_short_endian(&ind, my_endian());
      p->len += write(fd, &ind, sizeof(short int));
    }
  else
    {
      direct = find_good_lab(lab, args) - p->size;
      convert_endian(&direct, my_endian());
      p->len += write(fd, &direct, sizeof(int));
    }
}
 Elf32_Word dynamic_relocations::read_info (unsigned int ndx) {
   if (ndx >= size)
     return 0;
   if (use == AC_USE_REL)
     return convert_endian(4, rel[ndx].r_info, match_endian);
   else if (use == AC_USE_RELA)
     return convert_endian(4, rela[ndx].r_info, match_endian);
   return 0;
 }
Esempio n. 4
0
  bool ac_rtld::detect_static_glibc(int fd, bool match_endian) {
    Elf32_Ehdr    ehdr;
    Elf32_Shdr    shdr;
    unsigned i;

    lseek(fd, 0, SEEK_SET);
    
    //Test if it's an ELF file
    if ((read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) ||  // read header
        (strncmp((char *)ehdr.e_ident, ELFMAG, 4) != 0) ||          // test elf magic number
        0) {
      return false;
    }
    
    // first load the section name string table
    char *string_table = NULL;
    int   shoff = convert_endian(4,ehdr.e_shoff, match_endian);
    short shndx = convert_endian(2,ehdr.e_shstrndx, match_endian);
    short shsize = convert_endian(2,ehdr.e_shentsize, match_endian);
    
    lseek(fd, shoff+(shndx*shsize), SEEK_SET);
    if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) {
      return false;
    }
    
    string_table = (char *) malloc(convert_endian(4,shdr.sh_size, match_endian));
    lseek(fd, convert_endian(4,shdr.sh_offset, match_endian), SEEK_SET);
    if (read(fd, string_table, convert_endian(4,shdr.sh_size, match_endian)) !=
        (signed)convert_endian(4,shdr.sh_size, match_endian)) {
      free (string_table);
      return false;
    }
    
    for (i=0; i<convert_endian(2,ehdr.e_shnum, match_endian); i++) {
      
      lseek(fd, shoff + shsize*i, SEEK_SET);
      
      if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) {
        free (string_table);
        return false;
      }
      
      
      if (!strncmp(string_table+convert_endian(4,shdr.sh_name, match_endian), 
                   "__libc", 6)) {
        this->glibc = true;
        free(string_table);
        return true;
      }
    }
    free(string_table);
    return false;
  }
Esempio n. 5
0
 char * version_definitions::get_cur_name(){
   Elf32_Verdaux *aux;
   if (current_entry == NULL) return 0;
   if (current_entry->vd_aux == 0) return 0;
   aux = reinterpret_cast<Elf32_Verdaux *>(reinterpret_cast<char *>(current_entry) + current_entry->vd_aux);
   return (char *) strtab + convert_endian(4, aux->vda_name, match_endian);
 }
Esempio n. 6
0
  bool version_needed::set_entry (char * filename)
  {
    current_entry = reinterpret_cast<Elf32_Verneed *>(ver_needed);
    
    while(current_entry != NULL)
      {
	if (!strcmp(filename, get_cur_filename()))
	  {
	    current_aux_entry = reinterpret_cast<Elf32_Vernaux *>(reinterpret_cast<char *>(current_entry) + 
								  convert_endian(4, current_entry->vn_aux, match_endian));
	    return true;
	  }
	if (current_entry->vn_next == 0)
	  current_entry = NULL;
	else
	  current_entry = reinterpret_cast<Elf32_Verneed *>(reinterpret_cast<char *>(current_entry) + 
							    convert_endian(4, current_entry->vn_next, match_endian));
      }
    
    return false;
  }
Esempio n. 7
0
  bool version_definitions::set_entry(Elf32_Half index)
  {
    current_entry = reinterpret_cast<Elf32_Verdef *>(ver_def);
    
    while (current_entry != NULL)
      {
	if (convert_endian(2, current_entry->vd_ndx, match_endian) == index)
	  return true;
	
	if (current_entry->vd_next == 0)
	  current_entry = NULL;
	else
	  current_entry = reinterpret_cast<Elf32_Verdef *>(reinterpret_cast<char *>(current_entry) + convert_endian(4, current_entry->vd_next, match_endian));
      }
    return false;
  }
Esempio n. 8
0
/*
 * Write archive to file
 */
static int output_archive(const char *path)
{
	FILE *fp;

	convert_endian();

	fp = fopen(path, "wb");
	if (!fp) {
		fprintf(stderr, "Error: failed to open %s\n", path);
		fclose(fp);
		return -1;
	}
	if (fwrite(archive, sizeof(char), archive->size, fp) != archive->size) {
		fprintf(stderr, "Error: failed to write to %s\n", path);
		fclose(fp);
		return -1;
	}
	fclose(fp);
	printf("Wrote archive to %s\n", path);

	return 0;
}
Esempio n. 9
0
  bool version_definitions::set_entry(char *vername, Elf32_Word hash)
  {
    current_entry = reinterpret_cast<Elf32_Verdef *>(ver_def);
    
    while (current_entry != NULL)
      {
	if (get_cur_hash() == hash)
	  {
	    if (!strcmp(get_cur_name(), vername))
	      return true;
	  }
	if (current_entry->vd_next == 0)
	  current_entry = NULL;
	else
	  current_entry = reinterpret_cast<Elf32_Verdef *>(reinterpret_cast<char *>(current_entry) + convert_endian(4, current_entry->vd_next, match_endian));
      }
    return false;
  }
Esempio n. 10
0
 Elf32_Sword dynamic_relocations::read_addend (unsigned int ndx) {
   if (use != AC_USE_RELA || ndx >= size)
     return 0;
   return convert_endian(4, rela[ndx].r_addend, match_endian);
 }
Esempio n. 11
0
 /* Get current aux entry hash value */
 Elf32_Word version_needed::get_cur_hash()
 {
   if (current_aux_entry == NULL) return 0;
   return convert_endian(4, current_aux_entry->vna_hash, match_endian);
 }
Esempio n. 12
0
 bool version_needed::go_next_aux_entry()
 {
   if (current_aux_entry == NULL || current_aux_entry->vna_next == 0) return false;
   current_aux_entry = reinterpret_cast<Elf32_Vernaux *> (reinterpret_cast<char *>(current_aux_entry) + convert_endian(4, current_aux_entry->vna_next, match_endian));
   return true;
 }
Esempio n. 13
0
 /* Get current aux entry other field */
 Elf32_Half version_needed::get_cur_other()
 {
   if (current_aux_entry == NULL) return 0;
   return convert_endian(2, current_aux_entry->vna_other, match_endian);
 }
Esempio n. 14
0
int process_elf(char* filename, hash_node **hashtable)
{
  Elf32_Ehdr    ehdr;
  Elf32_Shdr    shdr;
  Elf32_Phdr    phdr;
  int           fd;
  unsigned int  i, j;
  unsigned int  match_endian;
  int shoff;         /* Section header offset */
  short shsize;      /* Section header size */
  short type;        /* ELF file type */
  char sections_patched = 0;
  char dynamic_found = FALSE;
  union _endian_test {
    char bytes[4];
    unsigned int word;
  } endian_test;

  /* Open ELF file */
  if (!filename || ((fd = open(filename, O_RDWR)) == -1)) {
    perror("Fatal error - open file");
    return -1;
  }

  /* Test if it is an ELF file */
  if ((read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) ||  // read header
      (strncmp((char *)ehdr.e_ident, ELFMAG, 4) != 0) ||          // test elf magic number
      0) {
    close(fd);
    fprintf(stderr, "Failure opening file: Not an ELF file or magic number mismatches.\n");
    exit(EXIT_FAILURE);
  }

  /* Our program is running little or big endian machine? */
  endian_test.word = 1;
  if (endian_test.bytes[0] == 1)
    match_endian = 0; /* little */
  else
    match_endian = 1; /* big */

  /* Big or little? */
  if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB) /* Big endian */ 
    {
      match_endian = !(match_endian ^ 1); 
    }
  else if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) /* Little endian */
    {
      match_endian = !(match_endian ^ 0); 
    } 
  else
    {
      fprintf(stderr, "Warning! Can't determine if ELF file is little or big endian. Machine default assumed.\n");
    }

  /* Testing file type */
  type = convert_endian(2, ehdr.e_type, match_endian);

  if (type != ET_EXEC && type != ET_REL && type != ET_DYN)
    {
      close(fd);
      fprintf(stderr, "Can't patch this file: this ELF is not a relocatable file, executable or DSO.\n");
      return ACRELCONVERT_FUNC_ERROR;
    }

  /* Trying to locate section header */
  shoff = convert_endian(4,ehdr.e_shoff, match_endian);
  shsize = convert_endian(2,ehdr.e_shentsize, match_endian);

  if (shoff == 0 || shsize == 0)
    { 
      unsigned int segment_type;
      short phnum = convert_endian(2, ehdr.e_phnum, match_endian);
      short phentsize = convert_endian(2, ehdr.e_phentsize, match_endian);
      int phoff = convert_endian(4, ehdr.e_phoff, match_endian);

      fprintf(stderr, "Warning: File's section header has been striped out. Can't locate ordinary relocation sections. We will still try patching dynamic relocations...\n");
      if (type != ET_DYN)
	{
	  fprintf(stderr, "Error: File is not a dynamic shared object, can't continue without section header.\n");
	  close(fd);
	  return ACRELCONVERT_FUNC_ERROR;
	}

      if (phnum == 0 || phoff == 0)
	{
	  fprintf(stderr, "Fatal error: Program headers are missing.\n");
	  close(fd);
	  return ACRELCONVERT_FUNC_ERROR;
	}
      /* Iterates through all program headers and locate the DYNAMIC segment type */
      for (i=0; i < phnum; i++)
	{
	  /* No need to continue looping if the DYNAMIC segment was already found.*/
	  if (dynamic_found)
	    break;

	  lseek(fd, phoff + phentsize * i, SEEK_SET);
	  if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) {
	    close(fd);
	    fprintf(stderr, "Fatal error: Couldn't read program header.\n");
	    return ACRELCONVERT_FUNC_ERROR;
	  }
	  segment_type = convert_endian(4, phdr.p_type, match_endian);
	  /* Found! */
	  if (segment_type == PT_DYNAMIC)
	    {
	      Elf32_Word p_filesz = convert_endian(4,phdr.p_filesz, match_endian), rel_size;
	      Elf32_Off  p_offset = convert_endian(4,phdr.p_offset, match_endian);

	      unsigned int rel_offset;
	      
	      Elf32_Dyn * buffer = NULL;
	      Elf32_Addr rel_addr;
	      int rel_type;

	      buffer = (Elf32_Dyn *) malloc(sizeof(char)*p_filesz);	      
	      if (buffer == NULL)
		{
		  close(fd);
		  fprintf(stderr, "Fatal error in buffer dynamic allocation.\n");
		  return ACRELCONVERT_FUNC_ERROR;
		}
	      lseek(fd, p_offset, SEEK_SET);
	      if (read(fd, buffer, p_filesz) != p_filesz)
		{
		  close(fd);
		  free(buffer);
		  fprintf(stderr, "Fatal error: Couldn't read DYNAMIC segment.\n");
		  return ACRELCONVERT_FUNC_ERROR;
		}
	      rel_type = 0;
	      rel_addr = 0;
	      rel_size = 0;
	      /* Iterates though all dynamic entries and finds REL/RELA records */
	      for (j = 0; j < (p_filesz / sizeof(Elf32_Dyn)); j++)
		{
		  switch (convert_endian(4,buffer[j].d_tag, match_endian))
		    {
		    case DT_REL:
		    case DT_RELA:
		      rel_type = convert_endian(4, buffer[j].d_tag, match_endian);
		      rel_addr = convert_endian(4, buffer[j].d_un.d_ptr, match_endian);
		      break;
		    case DT_RELSZ:
		    case DT_RELASZ:
		      rel_size = convert_endian(4, buffer[j].d_un.d_val, match_endian);
		      break;
		    default:
		      break;
		    }
		}
	      free(buffer);

	      /* If any info is missing, terminate */
	      if (rel_type == 0 || rel_addr == 0 || rel_size == 0)
		{
		  close(fd);
		  fprintf(stderr, "Could not locate a dynamic relocation section in this DSO.\n");
		  return ACRELCONVERT_FUNC_ERROR;
		}

	      rel_offset = 0;

	      /* Identify where, in the file, these relocations are (rel_offset) */
	      for (j=0; j < phnum; j++)
		{
		  lseek(fd, phoff + phentsize * i, SEEK_SET);
		  if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) {
		    close(fd);
		    fprintf(stderr, "Fatal error: Couldn't read program header.\n");
		    return ACRELCONVERT_FUNC_ERROR;
		  }
		  segment_type = convert_endian(4, phdr.p_type, match_endian);      
		  if (segment_type == PT_LOAD)
		    {
		      Elf32_Addr p_vaddr = convert_endian(4,phdr.p_vaddr, match_endian);
		      Elf32_Word p_filesz = convert_endian(4,phdr.p_filesz, match_endian);
		      Elf32_Off  p_offset = convert_endian(4,phdr.p_offset, match_endian);

		      /* Does this segment contains our dynrelocs section? */
		      if (p_vaddr <= rel_addr && p_vaddr + p_filesz >= rel_addr + rel_size)
			{
			  rel_offset = p_offset + (rel_addr - p_vaddr);
			}
		    }
		}
	      /* Not found */
	      if (rel_offset == 0)
		{
		  close(fd);
		  fprintf(stderr, "Could not locate the dynamic relocation section in this DSO.\n");
		  return ACRELCONVERT_FUNC_ERROR;
		}

	      /* Now we have rel_offset, rel_type and rel_size. Start patching relocations */
	      dynamic_found = TRUE;

	      lseek(fd, rel_offset, SEEK_SET);

	      if (patch_relocation_section(fd, rel_size, rel_type, hashtable, match_endian)
		  == ACRELCONVERT_FUNC_ERROR)
		{
		  close(fd);
		  fprintf(stderr, "Failed patching relocation codes at dynrelocs section.\n");
		  return ACRELCONVERT_FUNC_ERROR;
		}
	    }
	}
      if (!dynamic_found)
	{
	  close(fd);
	  fprintf(stderr, "Fatal error: Couldn't find any DYNAMIC segment in this DSO, preventing us from locating dynamic relocations section without a section headers table.\n");
	  return ACRELCONVERT_FUNC_ERROR;
	}
      
    }
  else /* We do have section headers information. */
    {
      int   shoff = convert_endian(4,ehdr.e_shoff, match_endian);
      short shsize = convert_endian(2,ehdr.e_shentsize, match_endian);
   
      
      /* Iterates though all sections. Patches all REL or RELA section types. */
      for (i=0; i<convert_endian(2,ehdr.e_shnum, match_endian); i++) {
	Elf32_Word shtype;
	int rel_type, rel_size;
	
	lseek(fd, shoff + shsize*i, SEEK_SET);
	
	if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) {
	  fprintf(stderr, "Error while trying to read section header.\n");
	  close(fd);
	  return ACRELCONVERT_FUNC_ERROR;
	}

	shtype = convert_endian(4, shdr.sh_type, match_endian);
	if (shtype == SHT_REL || shtype == SHT_RELA)
	  {
	    if (shtype == SHT_REL)
	      rel_type = DT_REL;
	    else
	      rel_type = DT_RELA;
	    rel_size = convert_endian(4, shdr.sh_size, match_endian);
	    lseek(fd, convert_endian(4, shdr.sh_offset, match_endian), SEEK_SET);

	    if (patch_relocation_section(fd, rel_size, rel_type, hashtable, match_endian)
		== ACRELCONVERT_FUNC_ERROR)
	      {
		close(fd);
		fprintf(stderr, "Failed patching relocation codes at section number %d.\n", i);
		return ACRELCONVERT_FUNC_ERROR;
	      }
	    sections_patched++;
	  }
      }

    }

  if (!sections_patched)
    {
      if (!dynamic_found)
	printf("\nNo relocation sections found. File has not been changed.\n");
    }
  else
    {
      printf("\nDone patching %d sections.\n", sections_patched);
    }

  /* Close file */
  close(fd);

  return ACRELCONVERT_FUNC_OK;
}
Esempio n. 15
0
int patch_relocation_section(unsigned int fd, unsigned int size, int rel_type, hash_node **hashtable,
			     unsigned int match_endian)
{
  unsigned int i;
  unsigned int entry_size = (rel_type == DT_REL) ? sizeof(Elf32_Rel) : sizeof(Elf32_Rela);
  unsigned int total = size / entry_size;

  if (rel_type == DT_REL) /* rel relocation type*/
    {
      Elf32_Rel rel;
      unsigned int new_code, old_code, sym;
      for (i = 0; i < total; i++)
	{
	  /* Read it. */
	  if (read(fd, &rel, sizeof(rel)) != sizeof(rel))
	    {
	      fprintf(stderr, "Couldn't read REL relocation number %d.\n", i);
	      return ACRELCONVERT_FUNC_ERROR;
	    }
	  /* Patch it. */
	  old_code = ELF32_R_TYPE(convert_endian(4, rel.r_info, match_endian));
	  sym = ELF32_R_SYM(convert_endian(4, rel.r_info, match_endian));
	  if (hash_get_value(hashtable, old_code, &new_code) == ACRELCONVERT_FUNC_ERROR)
	    {
	      fprintf(stderr, "Error: unrecognized relocation code 0x%X (%d), at relocation number %d\n", 
		      old_code, old_code, i);
	      return ACRELCONVERT_FUNC_ERROR;
	    }
	  rel.r_info = convert_endian(4, ELF32_R_INFO(sym, new_code), match_endian);
	  /* Write it back, patched. */
	  lseek(fd, - sizeof(rel), SEEK_CUR);
	  if (write(fd, &rel, sizeof(rel)) != sizeof(rel))
	    {
	      fprintf(stderr, "Error: couldn't write REL relocation number %d.\n", i);
	      return ACRELCONVERT_FUNC_ERROR;
	    }
	}
    }
  else  /* rela relocation type */ 
    {
      Elf32_Rela rela;
      unsigned int new_code, old_code, sym;
      for (i = 0; i < total; i++)
	{
	  /* Read it. */
	  if (read(fd, &rela, sizeof(rela)) != sizeof(rela))
	    {
	      fprintf(stderr, "Couldn't read RELA relocation number %d.\n", i);
	      return ACRELCONVERT_FUNC_ERROR;
	    }
	  /* Patch it. */
	  old_code = ELF32_R_TYPE(convert_endian(4, rela.r_info, match_endian));
	  sym = ELF32_R_SYM(convert_endian(4, rela.r_info, match_endian));
	  if (hash_get_value(hashtable, old_code, &new_code) == ACRELCONVERT_FUNC_ERROR)
	    {
	      fprintf(stderr, "Error: unrecognized relocation code 0x%X (%d), at relocation number %d\n", 
		      old_code, old_code, i);
	      return ACRELCONVERT_FUNC_ERROR;
	    }
	  rela.r_info = convert_endian(4, ELF32_R_INFO(sym, new_code), match_endian);
	  /* Write it back, patched. */
	  lseek(fd, - sizeof(rela), SEEK_CUR);
	  if (write(fd, &rela, sizeof(rela)) != sizeof(rela))
	    {
	      fprintf(stderr, "Error: couldn't write RELA relocation number %d.\n", i);
	      return ACRELCONVERT_FUNC_ERROR;
	    }
	} 
    }
  return ACRELCONVERT_FUNC_OK;
}
Esempio n. 16
0
 Elf32_Word version_definitions::get_cur_hash() {
   if (current_entry == NULL) return 0;
   return convert_endian(4, current_entry->vd_hash, match_endian);
 }
Esempio n. 17
0
 Elf32_Half version_definitions::get_cur_flags() {
   if (current_entry == NULL) return 0;
   return convert_endian(4, current_entry->vd_flags, match_endian);
 }
Esempio n. 18
0
 /* Return the filename (of current entry) */
 char * version_needed::get_cur_filename()
 {
   if (current_entry == NULL) return 0;
   return (char *) strtab + convert_endian(4, current_entry->vn_file, match_endian);
 }
Esempio n. 19
0
  bool link_node::link_node_setup(Elf32_Addr dynaddr, unsigned char *mem,
				  Elf32_Addr l_addr, unsigned int t, unsigned char *name,
				  version_needed *verneed, bool match_endian) {
    Elf32_Addr hashaddr = 0, symaddr= 0, straddr = 0, reladdr = 0,
      verneed_addr = 0, verdef_addr = 0, versym_addr = 0, init_addr = 0,
      init_addr_array = 0, init_addr_arraysz = 0, fini_addr = 0,
      fini_addr_array = 0, fini_addr_arraysz = 0;
    Elf32_Word pltrel = 0, relsize = 0;
    unsigned int reltype = 0;
    bool is_linux_runtime_linker = false;
    
    this->match_endian = match_endian;
    
    load_addr = l_addr;
    type = t;
    soname = name;
    this->mem = mem;
    
    dyn_info.load_dynamic_info(dynaddr, mem, match_endian);
    
    hashaddr = dyn_info.get_value(DT_HASH);
    symaddr = dyn_info.get_value(DT_SYMTAB);
    straddr = dyn_info.get_value(DT_STRTAB);
    verneed_addr = dyn_info.get_value(DT_VERNEED);
    verdef_addr = dyn_info.get_value(DT_VERDEF);
    versym_addr = dyn_info.get_value(DT_VERSYM);
    init_addr = dyn_info.get_value(DT_INIT);
    init_addr_array = dyn_info.get_value(DT_INIT_ARRAY);
    init_addr_arraysz = dyn_info.get_value(DT_INIT_ARRAYSZ);
    fini_addr = dyn_info.get_value(DT_FINI);
    fini_addr_array = dyn_info.get_value(DT_FINI_ARRAY);
    fini_addr_arraysz = dyn_info.get_value(DT_FINI_ARRAYSZ);

    if ( dyn_info.compare_library_soname ((char *)soname, get_program_interpreter())
         == 0) {
      is_linux_runtime_linker = true;
    }
    
    if (hashaddr) 
      hashaddr += l_addr;
    if (symaddr) 
      symaddr += l_addr;
    if (straddr) 
      straddr += l_addr;
    if (verneed_addr) 
      verneed_addr += l_addr;
    if (verdef_addr) 
      verdef_addr += l_addr;
    if (versym_addr) 
      versym_addr += l_addr;

    /* Configure init/fini addresses (avoid including the program
       interpreter) */
    if (!is_linux_runtime_linker && init_addr) {
      init_addr += l_addr;
      add_to_start_vector(init_addr);
    }
    if (!is_linux_runtime_linker && init_addr_arraysz && init_addr_array) {
      init_addr_array += l_addr;
      for (unsigned i = 0; i < init_addr_arraysz; i+= sizeof(Elf32_Addr)) {
        Elf32_Addr tmp = *(reinterpret_cast<Elf32_Addr *>(mem + 
                                                        init_addr_array +
                                                          i));
        tmp = convert_endian(sizeof(Elf32_Addr), tmp, match_endian);
        add_to_start_vector((unsigned) (tmp + l_addr));
      }
    }
    if (!is_linux_runtime_linker && fini_addr) {
      fini_addr += l_addr;
      add_to_fini_vector(fini_addr);
    }
    if (!is_linux_runtime_linker && fini_addr_arraysz && fini_addr_array) {
      fini_addr_array += l_addr;
      for (unsigned i = 0; i < fini_addr_arraysz; i+= sizeof(Elf32_Addr)) {
        Elf32_Addr tmp = *(reinterpret_cast<Elf32_Addr *>(mem + 
                                                        fini_addr_array +
                                                          i));
        tmp = convert_endian(sizeof(Elf32_Addr), tmp, match_endian);
        add_to_fini_vector((unsigned) (tmp + l_addr));
      }
    }

    /* Set back the adjusted value because dyn_info uses it when
       extracting needed libraries names. */
    dyn_info.set_value(DT_STRTAB, straddr);
    
    dyn_table.setup_hash(mem, hashaddr, symaddr, straddr, verdef_addr,
			 verneed_addr, versym_addr, match_endian);
    
    pltrel = dyn_info.get_value(DT_PLTREL);
    if (pltrel == 0) /* file has no relocations */
      {
	has_relocations = 0;
      }
    else
      {
	has_relocations = 1;
	reltype = (pltrel == DT_REL)? AC_USE_REL : AC_USE_RELA;
	reladdr = l_addr + dyn_info.get_value(pltrel); /* DT_REL or DT_RELA */
	if (reladdr == 0) /* No data relocations */
	  reladdr = l_addr = dyn_info.get_value(DT_JMPREL);
	relsize = dyn_info.get_value(pltrel + 1); /* DT_RELSZ or DT_RELASZ*/
	relsize += dyn_info.get_value(DT_PLTRELSZ);
	relsize /= (pltrel == DT_REL)? 8:12;

	dyn_relocs.setup(reladdr, relsize, mem, reltype, match_endian);
      }

    if (verneed != NULL)
      {
	/* we have special needs for this library*/
	if (verneed->set_entry((char *)name) == true)
	  {
              /* does not have version information, this is not the desired library */
	    if (!verdef_addr)
	      return false;
	    
	    do  /* For each verneeded aux entry, see if this library has the
		   desired version tag */
	      {
		if (dyn_table.get_verdefs()->set_entry(verneed->get_cur_vername(),
                                                         verneed->get_cur_hash()) == false)
		  { /* We don't have this version definition, see if it is
                       really necessary (not a weak def) */
		    if (!(verneed->get_cur_flags() & VER_FLG_WEAK))
		      return false; /* Library is old, reject it */
		  }
		
	      } while (verneed->go_next_aux_entry());
	  }
	
      }
    /* Library accepted */
    return true;
  }
Esempio n. 20
0
 /* Return the number of associated aux entries (of current entry) */
 Elf32_Half version_needed::get_cur_cnt()
 {
   if (current_entry == NULL) return 0;
   return convert_endian(2, current_entry->vn_cnt, match_endian);
 }