Example #1
0
static void	resolve_relocations(sym_strtab **list)
{
  Elf_Scn	*scn;
  Elf64_Shdr	*shdr;

  scn = NULL;
  while ((scn = elf_nextscn(e, scn)))
    {
      if ((shdr = elf64_getshdr(scn)) == NULL)
      	exit_error("gelf_getshdr() fail");
      if (shdr->sh_type == SHT_DYNSYM)
	{
	  Elf_Data	*data;
	  data = elf_getdata(scn, NULL);
	  dynsym_tab = (Elf64_Sym*)data->d_buf;
	}
      if (shdr->sh_type == SHT_STRTAB && shdr->sh_flags == SHF_ALLOC)
	{
	  Elf_Data	*data;
	  data = elf_getdata(scn, NULL);
	  dynsym_strtab = (char*)data->d_buf;
	}
    }
  if (!dynsym_tab)
    return;
  scn = NULL;
  while ((scn = elf_nextscn(e, scn)))
    {
      if ((shdr = elf64_getshdr(scn)) == NULL)
      	exit_error("gelf_getshdr() fail");
      if (shdr->sh_type == SHT_RELA)
	reloc_treatment(scn, shdr, list);
    }
}
Example #2
0
int ElfWriter::newSection(LIBDWARF_CALLBACK_NAME_TYPE name,
  uint64_t size, uint32_t type, uint64_t flags,
  uint64_t addr/* = 0*/) {
  Elf_Scn *scn = elf_newscn(m_elf);
  if (!scn) {
    logError("Unable to create new section");
    return -1;
  }
  Elf64_Shdr *sectionHdr = elf64_getshdr(scn);
  if (!sectionHdr) {
    logError("Unable to create section header");
    return -1;
  }
  int nameOffset = addSectionString(name);
  sectionHdr->sh_name = nameOffset;
  sectionHdr->sh_type = type;
  sectionHdr->sh_flags = flags;
  sectionHdr->sh_size = size;
  sectionHdr->sh_addr = addr;
  sectionHdr->sh_offset = 0;
  sectionHdr->sh_link = 0;
  sectionHdr->sh_info = 0;
  sectionHdr->sh_addralign = 1;
  sectionHdr->sh_entsize = 0;

  return elf_ndxscn(scn);
}
static struct code_template* function_template_load64(Elf* e, Elf64_Sym* func64)
{
    Elf_Scn* scn = elf_getscn(e, func64->st_shndx);
    assert(scn);
    
    Elf64_Shdr* shdr64 = elf64_getshdr(scn);
    assert(shdr64);
    
    return ct_load(e, scn, func64->st_value, func64->st_size,
        shdr64->sh_addralign);
}
Example #4
0
Elf_Scn* getSection(Elf *elf,const char *name)
{
	Elf64_Ehdr *ehdr = elf64_getehdr(elf);
	if(!ehdr) return NULL;

	Elf_Data *data = elf_getdata(elf_getscn(elf,ehdr->e_shstrndx),NULL);
	if(!data) return NULL;

	for(Elf_Scn *scn = NULL;(scn = elf_nextscn(elf,scn));) {
		Elf64_Shdr *shdr = elf64_getshdr(scn);
		if(shdr && !strcmp(name,(const char*)data->d_buf + shdr->sh_name)) return scn;
	}
	return NULL;
}
Example #5
0
static void	load_symtab(sym_strtab **list, Elf_Scn *sym_scn)
{
  Elf_Data	*data;
  size_t	nb_symbols;

  sym_shdr = elf64_getshdr(sym_scn);
  data = elf_getdata(sym_scn, NULL);

  symtab = (Elf64_Sym*)data->d_buf;
  nb_symbols = sym_shdr->sh_size / sym_shdr->sh_entsize;

  for (size_t i = 0; i < nb_symbols; ++i)
    if (ELF64_ST_TYPE(symtab[i].st_info) == STT_FUNC
	|| ELF64_ST_TYPE(symtab[i].st_info) == STT_NOTYPE)
      add_symbol(list, symtab[i].st_value,
		 elf_strptr(e, sym_shdr->sh_link, symtab[i].st_name));
}
Example #6
0
static Elf_Scn	*get_sym_shdr(void)
{
  Elf_Scn	*scn;
  Elf64_Shdr	*shdr;

  scn = NULL;
  while ((scn = elf_nextscn(e, scn)))
    {
      if ((shdr = elf64_getshdr(scn)) == NULL)
      	exit_error("gelf_getshdr() fail");
      if (shdr->sh_type == SHT_SYMTAB)
	break;
    }
  if (!scn)
    exit_error("symtab not found omg");
  return scn;
}
Example #7
0
int
write_shdr(elf_data_t *elf, Elf_Scn *scn, GElf_Shdr *shdr, size_t sidx, char **err)
{
  off_t off;
  size_t n, shdr_size;
  void *shdr_buf;

  if(!gelf_update_shdr(scn, shdr)) {
    (*err) = "failed to update section header";
    return -1;
  }

  if(elf->bits == 32) {
    shdr_buf = elf32_getshdr(scn);
    shdr_size = sizeof(Elf32_Shdr);
  } else {
    shdr_buf = elf64_getshdr(scn);
    shdr_size = sizeof(Elf64_Shdr);
  }

  if(!shdr_buf) {
    (*err) = "failed to get section header";
    return -1;
  }

  off = lseek(elf->fd, elf->ehdr.e_shoff + sidx*elf->ehdr.e_shentsize, SEEK_SET);
  if(off < 0) {
    (*err) = "lseek failed";
    return -1;
  }
    
  n = write(elf->fd, shdr_buf, shdr_size);
  if(n != shdr_size) {
    (*err) = "write failed";
    return -1;
  }

  return 0;
}
Example #8
0
int
xlate_named_init_elf(Elf * elf, const char *section_name,
	xlate_table_con * ret_tab_ptr)
{
   int retstatus  = XLATE_TB_STATUS_NO_ERROR;
   xlate_table_con newtab = 0;
   Elf_Scn *scn = 0;
   int is64bit = 0;
   char *ident;
   size_t identsize;
   Elf_Scn *xlscn = 0;
   Elf64_Shdr *shdr64 = 0;
   Elf32_Shdr *shdr32 = 0;
   Elf32_Ehdr *ehdr32 = 0;
   Elf64_Ehdr *ehdr64 = 0;
   Elf_Data   *xlatedata = 0;
   int stringindex = 0;
   char * sec_name;

   if(elf_kind(elf) != ELF_K_ELF) {
	return XLATE_TB_STATUS_NOT_ELF;
   }
   ident = elf_getident(elf,&identsize);

   if(ident == 0 || identsize < EI_NIDENT) {
     return  XLATE_TB_STATUS_ELF_IDENT_BAD;
   }
   if(ident[EI_CLASS] ==  ELFCLASS64) {
	is64bit = 1;
   }
   if(is64bit) {
	ehdr64 = elf64_getehdr(elf);
	if(ehdr64 == 0 ) {
	  return XLATE_TB_STATUS_ELF_EHDR_BAD;
	}
	stringindex = ehdr64->e_shstrndx;
   } else {
	ehdr32 = elf32_getehdr(elf);
	if(ehdr32 == 0 ) {
	  return XLATE_TB_STATUS_ELF_EHDR_BAD;
	}
	stringindex = ehdr32->e_shstrndx;
   }

   for(scn = elf_nextscn(elf,scn);  
	scn != 0 && xlscn == 0
		; scn = elf_nextscn(elf,scn)) {
	if(is64bit) {
	  shdr64 = elf64_getshdr(scn);
	  if(shdr64 == 0) {
	    return XLATE_TB_STATUS_ELF_SHDR_BAD;
	  }
	  sec_name = elf_strptr(elf,stringindex,shdr64->sh_name);
	  if(sec_name == 0) {
	    return XLATE_TB_STATUS_ELF_STRPTR_BAD;
	  }
	  if(shdr64->sh_type    != SHT_MIPS_XLATE &&
		shdr64->sh_type != SHT_MIPS_XLATE_DEBUG &&
		shdr64->sh_type != SHT_MIPS_XLATE_OLD ) {
		continue;
	  }
	  if(!streq(section_name,sec_name)) {
		continue;
	  }
	  xlscn = scn;
	  break;
	} else {
	  shdr32 = elf32_getshdr(scn);
	  if(shdr32 == 0) {
	    return XLATE_TB_STATUS_ELF_SHDR_BAD;
	  }
	  sec_name = elf_strptr(elf,stringindex,shdr32->sh_name);
	  if(sec_name == 0) {
	    return XLATE_TB_STATUS_ELF_STRPTR_BAD;
	  }
	  if(shdr32->sh_type    != SHT_MIPS_XLATE  &&
		shdr32->sh_type != SHT_MIPS_XLATE_DEBUG &&
		shdr32->sh_type != SHT_MIPS_XLATE_OLD ) {
		continue;
	  }
	  if(!streq(section_name,sec_name)) {
		continue;
	  }
	  xlscn = scn;
	  break;
	}
   }
   if(xlscn == 0) {
	return XLATE_TB_STATUS_NO_XLATE;
   }

   xlatedata = elf_getdata(xlscn,NULL);
   if(xlatedata == NULL || xlatedata->d_size == 0) {
	return XLATE_TB_STATUS_NO_XLATE_DATA;
   }
   
   newtab = (xlate_table_con)malloc(sizeof(struct xlate_table_con_s));
   if(newtab == NULL) {
	return XLATE_TB_STATUS_ALLOC_FAIL;
   }
   bzero(newtab,sizeof(struct xlate_table_con_s));


   newtab->xc_elf = elf;


   newtab->xc_section_data = xlatedata->d_buf;
   newtab->xc_data_size = xlatedata->d_size;
   if(newtab->xc_data_size != xlatedata->d_size) {
	/* we have a gigantic section and are compiled only 32 bit.
	** we simply cannot handle and I don't think the
        ** mmap would have worked anyway so we cannot really
	** get here.
	*/
     free(newtab);
     return XLATE_TB_STATUS_SECTION_TOO_BIG;
   }

   retstatus = _xlate_fill_in_table_data(newtab,is64bit);
   if(retstatus != XLATE_TB_STATUS_NO_ERROR) {
     free(newtab);
     return retstatus;
   }

   newtab->xc_valid_table         = VALID_TABLE_MAGIC;
   *ret_tab_ptr = newtab;
   return retstatus;
}
Example #9
0
static void print_relocinfo_64 (Dwarf_Debug dbg, Elf *elf)
{
#ifdef HAVE_ELF64_GETEHDR
    Elf_Scn *scn = NULL;
    Elf_Data *data;
    Elf64_Ehdr	    *ehdr64;
    Elf64_Shdr      *shdr64;
    char *scn_name;
    int i;

    if ((ehdr64 = elf64_getehdr(elf)) == NULL) {
	print_error(dbg, "DW_ELF_GETEHDR_ERROR",DW_DLV_OK, err); 
    }

    while ((scn = elf_nextscn(elf, scn)) != NULL) {

	if ((shdr64 = elf64_getshdr(scn)) == NULL) {
	    print_error(dbg, "DW_ELF_GETSHDR_ERROR",DW_DLV_OK, err); 
	}
	if ((scn_name = elf_strptr(elf,ehdr64->e_shstrndx, shdr64->sh_name)) 
	    == NULL) {
	    print_error(dbg, "DW_ELF_STRPTR_ERROR",DW_DLV_OK, err); 
	}
	if (shdr64->sh_type == SHT_SYMTAB) {
	    size_t sym_size = 0;
	    size_t count = 0;
	    if ((sym_64 = (Elf64_Sym *) get_scndata(scn, &sym_size)) == NULL) {
		print_error(dbg, "no symbol table data",DW_DLV_OK, err); 
	    }
	    count = sym_size / sizeof (Elf64_Sym);
	    sym_64 ++;
	    if ((sym_data_64 = read_64_syms(sym_64, count, elf, 
					    shdr64->sh_link)) == NULL) {
		print_error(dbg, "problem reading symbol table data",DW_DLV_OK, err); 
	    }
	}
	else if (strncmp(scn_name, ".rel.debug_", 11))
	    continue;
	else if (strcmp(scn_name, ".rel.debug_info") == 0) {
	    SECT_DATA_SET(DW_SECTION_REL_DEBUG_INFO)
	}
	else if (strcmp(scn_name, ".rel.debug_line") == 0) {
	    SECT_DATA_SET(DW_SECTION_REL_DEBUG_LINE)
	}
	else if (strcmp(scn_name, ".rel.debug_pubname") == 0) {
	    SECT_DATA_SET(DW_SECTION_REL_DEBUG_PUBNAME)
	}
	else if (strcmp(scn_name, ".rel.debug_aranges") == 0) {
	    SECT_DATA_SET(DW_SECTION_REL_DEBUG_ARANGES)
	}
	else if (strcmp(scn_name, ".rel.debug_abbrev") == 0) {
	    SECT_DATA_SET(DW_SECTION_REL_DEBUG_ABBREV)
	}
	else if (strcmp(scn_name, ".rel.debug_frame") == 0) {
	    SECT_DATA_SET(DW_SECTION_REL_DEBUG_FRAME)
	}
    } /* while */

    for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i ++) {
	if (sect_data[i].buf != NULL && sect_data[i].size > 0) {
	    print_reloc_information_64(i, sect_data[i].buf, sect_data[i].size);
	}
    }
#endif
}
Example #10
0
/*
    Given an Elf ptr, set up dbg with pointers
    to all the Dwarf data sections.
    Return NULL on error.

    This function is also responsible for determining
    whether the given object contains Dwarf information
    or not.  The test currently used is that it contains
    either a .debug_info or a .debug_frame section.  If 
    not, it returns DW_DLV_NO_ENTRY causing dwarf_init() also to 
    return DW_DLV_NO_ENTRY.  Earlier, we had thought of using only 
    the presence/absence of .debug_info to test, but we 
    added .debug_frame since there could be stripped objects 
    that have only a .debug_frame section for exception 
    processing.
    DW_DLV_NO_ENTRY or DW_DLV_OK or DW_DLV_ERROR
*/
static int
_dwarf_setup(Dwarf_Debug dbg, dwarf_elf_handle elf, Dwarf_Error * error)
{
#ifdef __SGI_FAST_LIBELF
    Elf64_Ehdr ehdr;
    Elf64_Shdr shdr;
    enum elf_sgi_error_type sres;
    unsigned char const* ehdr_ident;
#else
    Elf32_Ehdr *ehdr32;

#ifdef HAVE_ELF64_GETEHDR
    Elf64_Ehdr *ehdr64;
#endif
    Elf32_Shdr *shdr32;

#ifdef HAVE_ELF64_GETSHDR
    Elf64_Shdr *shdr64;
#endif
    Elf_Scn *scn;
    char *ehdr_ident;
#endif /* !defined(__SGI_FAST_LIBELF) */
    Dwarf_Half machine;
    char *scn_name;
    int is_64bit;
    int foundDwarf;

    Dwarf_Unsigned section_size;
    Dwarf_Unsigned section_count;
    Dwarf_Half section_index;

    foundDwarf = FALSE;
    dbg->de_elf = elf;

    dbg->de_assume_string_in_bounds = _dwarf_assume_string_bad;

#ifdef __SGI_FAST_LIBELF
    sres = elf_sgi_ehdr(elf, &ehdr);
    if (sres != ELF_SGI_ERROR_OK) {
	DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres),
			DW_DLV_ERROR);
    }
    ehdr_ident = ehdr.e_ident;
    section_count = ehdr.e_shnum;
    machine = ehdr.e_machine;
#else
    if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) {
	DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETIDENT_ERROR, DW_DLV_ERROR);
    }
#endif

    is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64);


    dbg->de_same_endian = 1;
    dbg->de_copy_word = memcpy;
#ifdef WORDS_BIGENDIAN
    dbg->de_big_endian_object = 1;
    if (ehdr_ident[EI_DATA] == ELFDATA2LSB) {
	dbg->de_same_endian = 0;
	dbg->de_big_endian_object = 0;
	dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
    }
#else /* little endian */
    dbg->de_big_endian_object = 0;
    if (ehdr_ident[EI_DATA] == ELFDATA2MSB) {
	dbg->de_same_endian = 0;
        dbg->de_big_endian_object = 1;
	dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
    }
#endif /* !WORDS_BIGENDIAN */

    /* The following de_length_size is Not Too Significant.
	Only used one calculation, and an appoximate one at that. */
    dbg->de_length_size = is_64bit ? 8 : 4;
    dbg->de_pointer_size = is_64bit ? 8 : 4;


#ifdef __SGI_FAST_LIBELF
    /* We've already loaded the ELF header, so there's nothing to do here */
#else
#ifdef HAVE_ELF64_GETEHDR
    if (is_64bit) {
	ehdr64 = elf64_getehdr(elf);
	if (ehdr64 == NULL) {
	    DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETEHDR_ERROR,
			    DW_DLV_ERROR);
	}
        section_count = ehdr64->e_shnum;
        machine = ehdr64->e_machine;
    } else
#endif
    {
	ehdr32 = elf32_getehdr(elf);
	if (ehdr32 == NULL) {
	    DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETEHDR_ERROR,
			    DW_DLV_ERROR);
	}
        section_count = ehdr32->e_shnum;
        machine = ehdr32->e_machine;
    }
#endif /* !defined(__SGI_FAST_LIBELF) */

    if (is_64bit && machine != EM_MIPS) {
        /* MIPS/IRIX makes pointer size and length size 8 for -64.
           Other platforms make length 4 always. */
        /* 4 here supports 32bit-offset dwarf2, as emitted by
           cygnus tools, and the dwarfv2.1 64bit extension setting. */
        dbg->de_length_size = 4;
    }

    /* We start at index 1 to skip the initial empty section. */
    for (section_index = 1; section_index < section_count; ++section_index) {

#ifdef __SGI_FAST_LIBELF
	sres = elf_sgi_shdr(elf, section_index, &shdr);
	if (sres != ELF_SGI_ERROR_OK) {
	    DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres),
			    DW_DLV_ERROR);
	}

	section_size = shdr.sh_size;

	sres = elf_sgi_string(elf, ehdr.e_shstrndx, shdr.sh_name, (char const** )&scn_name);
	if (sres != ELF_SGI_ERROR_OK) {
	    DWARF_DBG_ERROR(dbg, _dwarf_error_code_from_elf_sgi_error_code(sres),
			    DW_DLV_ERROR);
	}
#else /* !defined(__SGI_FAST_LIBELF) */
	scn = elf_getscn(elf, section_index);
	if (scn == NULL) {
	    DWARF_DBG_ERROR(dbg, DW_DLE_MDE,
			    DW_DLV_ERROR);
	}

#ifdef HAVE_ELF64_GETSHDR
	if (is_64bit) {
	    shdr64 = elf64_getshdr(scn);
	    if (shdr64 == NULL) {
		DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETSHDR_ERROR,
				DW_DLV_ERROR);
	    }

	    section_size = shdr64->sh_size;

	    if ((scn_name = elf_strptr(elf, ehdr64->e_shstrndx,
				       shdr64->sh_name))
		== NULL) {
		DWARF_DBG_ERROR(dbg, DW_DLE_ELF_STRPTR_ERROR,
				DW_DLV_ERROR);
	    }
	} else
#endif /* HAVE_ELF64_GETSHDR */
	{
	    if ((shdr32 = elf32_getshdr(scn)) == NULL) {
		DWARF_DBG_ERROR(dbg, DW_DLE_ELF_GETSHDR_ERROR, 0);
	    }

	    section_size = shdr32->sh_size;

	    if ((scn_name = elf_strptr(elf, ehdr32->e_shstrndx,
				       shdr32->sh_name)) == NULL) {
		DWARF_DBG_ERROR(dbg, DW_DLE_ELF_STRPTR_ERROR,
				DW_DLV_ERROR);
	    }
	}
#endif /* !defined(__SGI_FAST_LIBELF) */

	if (strncmp(scn_name, ".debug_", 7)
	    && strcmp(scn_name, ".eh_frame")
	    )
	    continue;

	else if (strcmp(scn_name, ".debug_info") == 0) {
	    if (dbg->de_debug_info != NULL) {
		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_INFO_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* Know no reason to allow empty debug_info section */
		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_INFO_NULL,
				DW_DLV_ERROR);
	    }
	    foundDwarf = TRUE;
	    dbg->de_debug_info_index = section_index;
	    dbg->de_debug_info_size = section_size;
	}

	else if (strcmp(scn_name, ".debug_abbrev") == 0) {
	    if (dbg->de_debug_abbrev != NULL) {
		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_ABBREV_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* Know no reason to allow empty debug_abbrev section */
		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_ABBREV_NULL,
				DW_DLV_ERROR);
	    }
	    dbg->de_debug_abbrev_index = section_index;
	    dbg->de_debug_abbrev_size = section_size;
	}

	else if (strcmp(scn_name, ".debug_aranges") == 0) {
	    if (dbg->de_debug_aranges_index != 0) {
		DWARF_DBG_ERROR(dbg,
				DW_DLE_DEBUG_ARANGES_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_aranges_index = section_index;
	    dbg->de_debug_aranges_size = section_size;
	}

	else if (strcmp(scn_name, ".debug_line") == 0) {
	    if (dbg->de_debug_line_index != 0) {
		DWARF_DBG_ERROR(dbg,
				DW_DLE_DEBUG_LINE_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_line_index = section_index;
	    dbg->de_debug_line_size = section_size;
	}

	else if (strcmp(scn_name, ".debug_frame") == 0) {
	    if (dbg->de_debug_frame_index != 0) {
		DWARF_DBG_ERROR(dbg,
				DW_DLE_DEBUG_FRAME_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_frame_index = section_index;
	    dbg->de_debug_frame_size = section_size;
	    foundDwarf = TRUE;
	} else if (strcmp(scn_name, ".eh_frame") == 0) {
	    /* gnu egcs-1.1.2 data */
	    if (dbg->de_debug_frame_eh_gnu_index != 0) {
		DWARF_DBG_ERROR(dbg,
				DW_DLE_DEBUG_FRAME_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_frame_eh_gnu_index = section_index;
	    dbg->de_debug_frame_size_eh_gnu = section_size;
	    foundDwarf = TRUE;
	}

	else if (strcmp(scn_name, ".debug_loc") == 0) {
	    if (dbg->de_debug_loc_index != 0) {
		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_LOC_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_loc_index = section_index;
	    dbg->de_debug_loc_size = section_size;
	}


	else if (strcmp(scn_name, ".debug_pubnames") == 0) {
	    if (dbg->de_debug_pubnames_index != 0) {
		DWARF_DBG_ERROR(dbg, DW_DLE_DEBUG_PUBNAMES_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_pubnames_index = section_index;
	    dbg->de_debug_pubnames_size = section_size;
	}

	else if (strcmp(scn_name, ".debug_str") == 0) {
	    if (dbg->de_debug_str_index != 0) {
		DWARF_DBG_ERROR(dbg,
				DW_DLE_DEBUG_STR_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_str_index = section_index;
	    dbg->de_debug_str_size = section_size;
	}

	else if (strcmp(scn_name, ".debug_funcnames") == 0) {
	    if (dbg->de_debug_funcnames_index != 0) {
		DWARF_DBG_ERROR(dbg,
				DW_DLE_DEBUG_FUNCNAMES_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_funcnames_index = section_index;
	    dbg->de_debug_funcnames_size = section_size;
	}

	else if (strcmp(scn_name, ".debug_typenames") == 0) {
	    if (dbg->de_debug_typenames_index != 0) {
		DWARF_DBG_ERROR(dbg,
				DW_DLE_DEBUG_TYPENAMES_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_typenames_index = section_index;
	    dbg->de_debug_typenames_size = section_size;
	}

	else if (strcmp(scn_name, ".debug_varnames") == 0) {
	    if (dbg->de_debug_varnames_index != 0) {
		DWARF_DBG_ERROR(dbg,
				DW_DLE_DEBUG_VARNAMES_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_varnames_index = section_index;
	    dbg->de_debug_varnames_size = section_size;
	}

	else if (strcmp(scn_name, ".debug_weaknames") == 0) {
	    if (dbg->de_debug_weaknames_index != 0) {
		DWARF_DBG_ERROR(dbg,
				DW_DLE_DEBUG_WEAKNAMES_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_weaknames_index = section_index;
	    dbg->de_debug_weaknames_size = section_size;
	} else if (strcmp(scn_name, ".debug_macinfo") == 0) {
	    if (dbg->de_debug_macinfo_index != 0) {
		DWARF_DBG_ERROR(dbg,
				DW_DLE_DEBUG_MACINFO_DUPLICATE,
				DW_DLV_ERROR);
	    }
	    if (section_size == 0) {
		/* a zero size section is just empty. Ok, no error */
		continue;
	    }
	    dbg->de_debug_macinfo_index = section_index;
	    dbg->de_debug_macinfo_size = section_size;
	}
    }
    if (foundDwarf) {
	return DW_DLV_OK;
    }

    return (DW_DLV_NO_ENTRY);
}
Example #11
0
int
xlate_init_elf(Elf * elf, int open_debug_table,
	xlate_table_con * ret_tab_ptr)
{
   int res;
   Elf32_Word wanttype;
   Elf_Scn *scn = 0;
   int is64bit = 0;
   char *ident;
   size_t identsize;
   Elf64_Shdr *shdr64 = 0;
   Elf32_Shdr *shdr32 = 0;
   Elf32_Ehdr *ehdr32 = 0;
   Elf64_Ehdr *ehdr64 = 0;
   int stringindex = 0;
   char * sec_name;

   if(elf_kind(elf) != ELF_K_ELF) {
	return XLATE_TB_STATUS_NOT_ELF;
   }
   ident = elf_getident(elf,&identsize);

   if(open_debug_table == XLATE_OPEN_STD_TABLE) {
	/* we take the first SHT_MIPS_XLATE*/
	wanttype = SHT_MIPS_XLATE;
   } else if(open_debug_table == XLATE_OPEN_DEBUG_TABLE) {
	/* we take the first SHT_MIPS_XLATE_DEBUG */
	wanttype = SHT_MIPS_XLATE_DEBUG;
   } else {
	return XLATE_TB_STATUS_NO_XLATE;
   }
   res = XLATE_TB_STATUS_NO_XLATE;
   if(ident == 0 || identsize < EI_NIDENT) {
     return  XLATE_TB_STATUS_ELF_IDENT_BAD;
   }
   if(ident[EI_CLASS] ==  ELFCLASS64) {
	is64bit = 1;
   }
   if(is64bit) {
	ehdr64 = elf64_getehdr(elf);
	if(ehdr64 == 0 ) {
	  return XLATE_TB_STATUS_ELF_EHDR_BAD;
	}
	stringindex = ehdr64->e_shstrndx;
   } else {
	ehdr32 = elf32_getehdr(elf);
	if(ehdr32 == 0 ) {
	  return XLATE_TB_STATUS_ELF_EHDR_BAD;
	}
	stringindex = ehdr32->e_shstrndx;
   }

   for(scn = elf_nextscn(elf,scn);  
	scn != 0 
		; scn = elf_nextscn(elf,scn)) {
	if(is64bit) {
	  shdr64 = elf64_getshdr(scn);
	  if(shdr64 == 0) {
	    return XLATE_TB_STATUS_ELF_SHDR_BAD;
	  }
	  sec_name = elf_strptr(elf,stringindex,shdr64->sh_name);
	  if(sec_name == 0) {
	    return XLATE_TB_STATUS_ELF_STRPTR_BAD;
	  }
	  if(shdr64->sh_type != wanttype) {
		continue;
	  }
	  res = xlate_named_init_elf(elf,
		sec_name,ret_tab_ptr);
	  return res;
	} else {
	  shdr32 = elf32_getshdr(scn);
	  if(shdr32 == 0) {
	    return XLATE_TB_STATUS_ELF_SHDR_BAD;
	  }
	  sec_name = elf_strptr(elf,stringindex,shdr32->sh_name);
	  if(sec_name == 0) {
	    return XLATE_TB_STATUS_ELF_STRPTR_BAD;
	  }
	  if(shdr32->sh_type != wanttype) {
		continue;
	  }
	  res = xlate_named_init_elf(elf,
		sec_name,ret_tab_ptr);
	  return res;
	}
   }

   return res;
}
int
elf_compress_gnu (Elf_Scn *scn, int inflate, unsigned int flags)
{
  if (scn == NULL)
    return -1;

  if ((flags & ~ELF_CHF_FORCE) != 0)
    {
      __libelf_seterrno (ELF_E_INVALID_OPERAND);
      return -1;
    }

  bool force = (flags & ELF_CHF_FORCE) != 0;

  Elf *elf = scn->elf;
  GElf_Ehdr ehdr;
  if (gelf_getehdr (elf, &ehdr) == NULL)
    return -1;

  int elfclass = elf->class;
  int elfdata = ehdr.e_ident[EI_DATA];

  Elf64_Xword sh_flags;
  Elf64_Word sh_type;
  Elf64_Xword sh_addralign;
  if (elfclass == ELFCLASS32)
    {
      Elf32_Shdr *shdr = elf32_getshdr (scn);
      if (shdr == NULL)
	return -1;

      sh_flags = shdr->sh_flags;
      sh_type = shdr->sh_type;
      sh_addralign = shdr->sh_addralign;
    }
  else
    {
      Elf64_Shdr *shdr = elf64_getshdr (scn);
      if (shdr == NULL)
	return -1;

      sh_flags = shdr->sh_flags;
      sh_type = shdr->sh_type;
      sh_addralign = shdr->sh_addralign;
    }

  if ((sh_flags & SHF_ALLOC) != 0)
    {
      __libelf_seterrno (ELF_E_INVALID_SECTION_FLAGS);
      return -1;
    }

  if (sh_type == SHT_NULL || sh_type == SHT_NOBITS)
    {
      __libelf_seterrno (ELF_E_INVALID_SECTION_TYPE);
      return -1;
    }

  /* For GNU compression we cannot really know whether the section is
     already compressed or not.  Just try and see what happens...  */
  // int compressed = (sh_flags & SHF_COMPRESSED);
  if (inflate == 1)
    {
      size_t hsize = 4 + 8; /* GNU "ZLIB" + 8 byte size.  */
      size_t orig_size, new_size, orig_addralign;
      void *out_buf = __libelf_compress (scn, hsize, elfdata,
					 &orig_size, &orig_addralign,
					 &new_size, force);

      /* Compression would make section larger, don't change anything.  */
      if (out_buf == (void *) -1)
	return 0;

      /* Compression failed, return error.  */
      if (out_buf == NULL)
	return -1;

      uint64_t be64_size = htobe64 (orig_size);
      memmove (out_buf, "ZLIB", 4);
      memmove (out_buf + 4, &be64_size, sizeof (be64_size));

      /* We don't know anything about sh_entsize, sh_addralign and
	 sh_flags won't have a SHF_COMPRESSED hint in the GNU format.
	 Just adjust the sh_size.  */
      if (elfclass == ELFCLASS32)
	{
	  Elf32_Shdr *shdr = elf32_getshdr (scn);
	  shdr->sh_size = new_size;
	}
      else
	{
	  Elf64_Shdr *shdr = elf64_getshdr (scn);
	  shdr->sh_size = new_size;
	}

      __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_BYTE);

      /* The section is now compressed, we could keep the uncompressed
	 data around, but since that might have been multiple Elf_Data
	 buffers let the user uncompress it explicitly again if they
	 want it to simplify bookkeeping.  */
      scn->zdata_base = NULL;

      return 1;
    }
  else if (inflate == 0)
    {
      /* In theory the user could have constucted a compressed section
	 by hand.  But we always just take the rawdata directly and
	 decompress that.  */
      Elf_Data *data = elf_rawdata (scn, NULL);
      if (data == NULL)
	return -1;

      size_t hsize = 4 + 8; /* GNU "ZLIB" + 8 byte size.  */
      if (data->d_size < hsize || memcmp (data->d_buf, "ZLIB", 4) != 0)
	{
          __libelf_seterrno (ELF_E_NOT_COMPRESSED);
	  return -1;
	}

      /* There is a 12-byte header of "ZLIB" followed by
	 an 8-byte big-endian size.  There is only one type and
	 Alignment isn't preserved separately.  */
      uint64_t gsize;
      memcpy (&gsize, data->d_buf + 4, sizeof gsize);
      gsize = be64toh (gsize);

      /* One more sanity check, size should be bigger than original
	 data size plus some overhead (4 chars ZLIB + 8 bytes size + 6
	 bytes zlib stream overhead + 5 bytes overhead max for one 16K
	 block) and should fit into a size_t.  */
      if (gsize + 4 + 8 + 6 + 5 < data->d_size || gsize > SIZE_MAX)
	{
	  __libelf_seterrno (ELF_E_NOT_COMPRESSED);
	  return -1;
	}

      size_t size = gsize;
      size_t size_in = data->d_size - hsize;
      void *buf_in = data->d_buf + hsize;
      void *buf_out = __libelf_decompress (buf_in, size_in, size);
      if (buf_out == NULL)
	return -1;

      /* We don't know anything about sh_entsize, sh_addralign and
	 sh_flags won't have a SHF_COMPRESSED hint in the GNU format.
	 Just adjust the sh_size.  */
      if (elfclass == ELFCLASS32)
	{
	  Elf32_Shdr *shdr = elf32_getshdr (scn);
	  shdr->sh_size = size;
	}
      else
	{
	  Elf64_Shdr *shdr = elf64_getshdr (scn);
	  shdr->sh_size = size;
	}

      __libelf_reset_rawdata (scn, buf_out, size, sh_addralign,
			      __libelf_data_type (elf, sh_type));

      scn->zdata_base = buf_out;

      return 1;
    }
  else
    {
      __libelf_seterrno (ELF_E_UNKNOWN_COMPRESSION_TYPE);
      return -1;
    }
}
Example #13
0
/*  dwarf_elf_object_access_get_section()

    If writing a function vaguely like this for a non-elf object,
    be sure that when section-index is passed in as zero that
    you set the fields in *ret_scn to reflect an empty section
    with an empty string as the section name.  Adjust your
    section indexes of your non-elf-reading-code
    for all the necessary functions in Dwarf_Obj_Access_Methods_s
    accordingly.
*/
static
int
dwarf_elf_object_access_get_section_info(
    void* obj_in,
    Dwarf_Half section_index,
    Dwarf_Obj_Access_Section* ret_scn,
    int* error)
{
    dwarf_elf_object_access_internals_t*obj =
        (dwarf_elf_object_access_internals_t*)obj_in;

    Elf32_Shdr *shdr32 = 0;

#ifdef HAVE_ELF64_GETSHDR
    Elf64_Shdr *shdr64 = 0;
#endif
    Elf_Scn *scn = 0;


    scn = elf_getscn(obj->elf, section_index);
    if (scn == NULL) {
        *error = DW_DLE_MDE;
        return DW_DLV_ERROR;
    }
    if (obj->is_64bit) {
#ifdef HAVE_ELF64_GETSHDR
        shdr64 = elf64_getshdr(scn);
        if (shdr64 == NULL) {
            *error = DW_DLE_ELF_GETSHDR_ERROR;
            return DW_DLV_ERROR;
        }

        /*  Get also section 'sh_type' and sh_info' fields, so the caller
            can use it for additional tasks that require that info. */
        ret_scn->type = shdr64->sh_type;
        ret_scn->size = shdr64->sh_size;
        ret_scn->addr = shdr64->sh_addr;
        ret_scn->link = shdr64->sh_link;
        ret_scn->info = shdr64->sh_info;
        ret_scn->entrysize = shdr64->sh_entsize;
        ret_scn->name = elf_strptr(obj->elf, obj->ehdr64->e_shstrndx,
            shdr64->sh_name);
        if (ret_scn->name == NULL) {
            *error = DW_DLE_ELF_STRPTR_ERROR;
            return DW_DLV_ERROR;
        }
        return DW_DLV_OK;
#else
        *error = DW_DLE_MISSING_ELF64_SUPPORT;
        return DW_DLV_ERROR;
#endif /* HAVE_ELF64_GETSHDR */
    }
    if ((shdr32 = elf32_getshdr(scn)) == NULL) {
        *error = DW_DLE_ELF_GETSHDR_ERROR;
        return DW_DLV_ERROR;
    }

    /*  Get also the section type, so the caller can use it for
        additional tasks that require to know the section type. */
    ret_scn->type = shdr32->sh_type;
    ret_scn->size = shdr32->sh_size;
    ret_scn->addr = shdr32->sh_addr;
    ret_scn->link = shdr32->sh_link;
    ret_scn->info = shdr32->sh_info;
    ret_scn->entrysize = shdr32->sh_entsize;
    ret_scn->name = elf_strptr(obj->elf, obj->ehdr32->e_shstrndx,
        shdr32->sh_name);
    if (ret_scn->name == NULL) {
        *error = DW_DLE_ELF_STRPTR_ERROR;
        return DW_DLV_ERROR;
    }
    return DW_DLV_OK;
}
static uint32_t* ExtractIsaBinaryFromElfBinary(uint64_t    isaOffset,
                                               const void* pBinary,
                                               size_t      binarySize)
{
    if (nullptr == pBinary || 0 == binarySize)
    {
        return nullptr;
    }

    // get isa binary from .hsatext section with a relative byte offset (isaOffset)

    // Determine the ELF type:
    bool isELF = false;
    bool isELF32 = false;
    bool isELF64 = false;

    // The ELF executable header is 16 bytes:
    if (16 < binarySize)
    {
        // Check for the ELF header start:
        const unsigned char* pBinaryAsUBytes = (const unsigned char*)pBinary;
        isELF = ((0x7f == pBinaryAsUBytes[0]) &&
                 ('E'  == pBinaryAsUBytes[1]) &&
                 ('L'  == pBinaryAsUBytes[2]) &&
                 ('F'  == pBinaryAsUBytes[3]));
        isELF32 = isELF && (0x01 == pBinaryAsUBytes[4]);
        isELF64 = isELF && (0x02 == pBinaryAsUBytes[4]);
    }

    // Validate:
    if (!isELF)
    {
        return nullptr;
    }

    if (!isELF32 && !isELF64)
    {
        assert(!"Unsupported ELF sub-format!");
        return nullptr;
    }

    // Set the version of elf:
    elf_version(EV_CURRENT);

    // Initialize the binary as ELF from memory:
    Elf* pContainerElf = elf_memory((char*)pBinary, binarySize);

    if (nullptr == pContainerElf)
    {
        return nullptr;
    }

    // First get the .hsatext section:
    static const std::string isaSectionName = ".hsatext";

    // Get the shared strings section:
    size_t sectionHeaderStringSectionIndex = 0;
    int rcShrstr = elf_getshdrstrndx(pContainerElf, &sectionHeaderStringSectionIndex);

    if ((0 != rcShrstr) || (0 == sectionHeaderStringSectionIndex))
    {
        return nullptr;
    }

    // Iterate the sections to find the isa section
    Elf_Scn* pCurrentSection = elf_nextscn(pContainerElf, nullptr);

    while (nullptr != pCurrentSection)
    {
        size_t strOffset = 0;

        if (isELF32)
        {
            // Get the section header:
            Elf32_Shdr* pCurrentSectionHeader = elf32_getshdr(pCurrentSection);

            if (nullptr != pCurrentSectionHeader)
            {
                // Get the name and link:
                strOffset = pCurrentSectionHeader->sh_name;
            }
        }
        else if (isELF64)
        {
            // Get the section header:
            Elf64_Shdr* pCurrentSectionHeader = elf64_getshdr(pCurrentSection);

            if (nullptr != pCurrentSectionHeader)
            {
                // Get the name and link:
                strOffset = pCurrentSectionHeader->sh_name;
            }
        }

        // Get the current section's name:
        char* pCurrentSectionName = elf_strptr(pContainerElf, sectionHeaderStringSectionIndex, strOffset);

        if (nullptr != pCurrentSectionName)
        {
            if (isaSectionName == pCurrentSectionName)
            {
                // Get the section's data:
                Elf_Data* pSectionData = elf_getdata(pCurrentSection, nullptr);

                if (nullptr != pSectionData)
                {
                    // Found the section, no need to continue:
                    // the isa binary is prefixed with an amd_kernel_code_t structure
                    uint64_t buffer = reinterpret_cast<uint64_t>(pSectionData->d_buf) + isaOffset + sizeof(amd_kernel_code_t);
                    return reinterpret_cast<uint32_t*>(buffer);
                }
            }
        }

        // Get the next section:
        pCurrentSection = elf_nextscn(pContainerElf, pCurrentSection);
    }

    return nullptr;
}
Example #15
0
int main(int argc,char *argv[])
{
	if(argc<2) {
		printf("Usage: %s [elf path]\n",argv[0]);
		return 0;
	}

	int fd = open(argv[1],OFLAGS);
	if(fd<0) {
		fprintf(stderr,"Unable to open elf file: %s\n",argv[1]);
		return 1;
	}

	elf_version(EV_CURRENT);
	
	Elf *elf = elf_begin(fd,ELF_C_READ,NULL);
	if(!elf) {
		fprintf(stderr,"libelf could not read elf file: %s\n",elf_errmsg(elf_errno()));
		return 1;
	}

	Elf_Scn *prx = getSection(elf,".sys_proc_prx_param");
	if(!prx || memcmp(elf_getdata(prx,NULL)->d_buf,prx_magic,sizeof(prx_magic))) {
		fprintf(stderr,"elf does not have a prx parameter section.\n");
		return 1;
	}

	Elf_Scn *stubsection = getSection(elf,".lib.stub");
	Elf_Data *stubdata = elf_getdata(stubsection,NULL);
	Elf64_Shdr *stubshdr = elf64_getshdr(stubsection);
	Stub *stubbase = (Stub*)stubdata->d_buf;
	size_t stubcount = stubdata->d_size/sizeof(Stub);
	Elf_Scn *fnidsection = getSection(elf,".rodata.sceFNID");
	Elf64_Shdr *fnidshdr = elf64_getshdr(fnidsection);
	for(Stub *stub = stubbase;stub<stubbase + stubcount;stub++) {
		uint32_t fnid = BE32(stub->fnid);
		uint32_t end = fnidshdr->sh_addr + fnidshdr->sh_size;
		for(Stub *substub = stubbase;substub<(stubbase + stubcount);substub++) {
			if(stub==substub) continue;

			uint32_t newfnid = BE32(substub->fnid);
			if(newfnid>=fnid && newfnid<end) end = newfnid;
		}

		uint16_t fnidcount = (end - fnid)/4;
		if(BE16(stub->imports)!=fnidcount) {
			lseek(fd,stubshdr->sh_offset + (stub - stubbase)*sizeof(Stub)+offsetof(Stub,imports),SEEK_SET);
			fnidcount = BE16(fnidcount);
			if(write(fd,&fnidcount,sizeof(fnidcount))!=sizeof(fnidcount)) {
				printf("Error occurred during write in %s:%d\n",__FILE__,__LINE__);
			}
		}
	}

	Elf_Scn *opdsection = getSection(elf,".opd");
	Elf_Data *opddata = elf_getdata(opdsection,NULL);
	Elf64_Shdr *opdshdr = elf64_getshdr(opdsection);

	Opd64 *opdbase = (Opd64*)opddata->d_buf;
	size_t opdcount = opddata->d_size/sizeof(Opd64);
	for(Opd64 *opd = opdbase;opd<(opdbase + opdcount);opd++) {
		opd->data = BE64(((BE64(opd->func)<<32ULL) | (BE64(opd->rtoc)&0xffffffffULL)));
		lseek(fd,opdshdr->sh_offset + (opd - opdbase)*sizeof(Opd64),SEEK_SET);
		if(write(fd,opd,sizeof(Opd64))!=sizeof(Opd64)) {
			printf("Error occurred during write in %s:%d\n",__FILE__,__LINE__);
		}
	}

	elf_end(elf);
	close(fd);

	return 0;
}