Exemple #1
0
/*
 * MIPS doesn't have traditional got.plt entries with corresponding
 * relocations.
 *
 * sym_index is an offset into the external GOT entries. Filter out
 * stuff that are not functions.
 */
int
arch_get_sym_info(struct ltelf *lte, const char *filename,
		  size_t sym_index, GElf_Rela *rela, GElf_Sym *sym)
{
	const char *name;

	if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
		return elf_get_sym_info(lte, filename, sym_index, rela, sym);
	}

	/* Fixup the offset.  */
	sym_index += lte->arch.mips_gotsym;

	if (gelf_getsym(lte->dynsym, sym_index, sym) == NULL){
		error(EXIT_FAILURE, 0,
			"Couldn't get relocation from \"%s\"", filename);
	}

	name = lte->dynstr + sym->st_name;
	if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC) {
		debug(2, "sym %s not a function", name);
		return -1;
	}

	return 0;
}
static uint_t
dt_module_syminit64(dt_module_t *dmp)
{
	const Elf64_Sym *sym = dmp->dm_symtab.cts_data;
	const char *base = dmp->dm_strtab.cts_data;
	size_t ss_size = dmp->dm_strtab.cts_size;
	uint_t i, n = dmp->dm_nsymelems;
	uint_t asrsv = 0;

	for (i = 0; i < n; i++, sym++) {
		const char *name = base + sym->st_name;
		uchar_t type = ELF64_ST_TYPE(sym->st_info);

		if (type >= STT_NUM || type == STT_SECTION)
			continue; /* skip sections and unknown types */

		if (sym->st_name == 0 || sym->st_name >= ss_size)
			continue; /* skip null or invalid names */

		if (sym->st_value != 0 &&
		    (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))
			asrsv++; /* reserve space in the address map */

		dt_module_symhash_insert(dmp, name, i);
	}

	return (asrsv);
}
Exemple #3
0
static SYM64 *
read_64_syms(Elf64_Sym *data, size_t num, Elf *elf, Elf64_Word link)
{
#ifdef HAVE_ELF64_GETEHDR

    SYM64 *s, *buf;
    size_t i;
    if( (buf = (SYM64 *)calloc(num, sizeof(SYM64)) ) == NULL) {
	return NULL;
    }
    s = buf;	/* save pointer to head of array */
    for(i=1; i<num; i++,data++,buf++) {
	buf->indx = i;
	buf->name = (char *)elf_strptr(elf, link, data->st_name);
	buf->value = data->st_value;
	buf->size = data->st_size;
	buf->type = ELF64_ST_TYPE(data->st_info);
	buf->bind = ELF64_ST_BIND(data->st_info);
	buf->other = data->st_other;
	buf->shndx = data->st_shndx;
    }	/* end for loop */
    return(s);
#else
    return 0;
#endif /* HAVE_ELF64_GETEHDR */
}
int prepare_mod_for_load(struct LKM_Module *lkm_mod, int sym_index, int str_index)
{
	int i,ret=0, flag=0;
	struct Secthdr *secthdr = lkm_mod->sect_hdr;
	struct Symhdr *tsymhdr,*symhdr = (void *)(lkm_mod->tmp_buf + secthdr[sym_index].sh_offset);
        tsymhdr = symhdr;
        char *sttab = (void *)(lkm_mod->tmp_buf + secthdr[str_index].sh_offset);
        size_t sym_size = secthdr[sym_index].sh_size / (sizeof(struct Symhdr));
        i=0;
        while(i < sym_size){
                if(ELF64_ST_TYPE(tsymhdr->st_info) == STT_FUNC){
			if((ret = strcmp("lkm_init", sttab + tsymhdr->st_name)) == 0){
				modules_lkm[mod_num].init_mod = (void (*) (void))lkm_mod->text_addr + tsymhdr->st_value;
				flag++;
			}else if((ret = strcmp("lkm_exit", sttab + tsymhdr->st_name)) == 0){
                        	modules_lkm[mod_num].unload_mod = (void (*) (void))lkm_mod->text_addr + tsymhdr->st_value;
				flag++;
			}else if((ret = strlen(sttab + tsymhdr->st_name)) != 0){
				insert_symbol(sttab + tsymhdr->st_name, (uintptr_t)(lkm_mod->text_addr + tsymhdr->st_value), modules_lkm[mod_num].name);
//				cprintf("Inserting Symbol Name : %s Symbol addr: %x \n", sttab + tsymhdr->st_name, (uintptr_t)(lkm_mod->text_addr + tsymhdr->st_value));
			}	
                }
                i++;
                tsymhdr++;
        }
	if(flag != 2)
		return -1;
	return 0;
}
Exemple #5
0
/*
 * Given a symbol table index, return the type of the data object described
 * by the corresponding entry in the symbol table.
 */
ctf_id_t
ctf_lookup_by_symbol(ctf_file_t *fp, ulong_t symidx)
{
	const ctf_sect_t *sp = &fp->ctf_symtab;
	ctf_id_t type;

	if (sp->cts_data == NULL)
		return (ctf_set_errno(fp, ECTF_NOSYMTAB));

	if (symidx >= fp->ctf_nsyms)
		return (ctf_set_errno(fp, EINVAL));

	if (sp->cts_entsize == sizeof (Elf32_Sym)) {
		const Elf32_Sym *symp = (Elf32_Sym *)sp->cts_data + symidx;
		if (ELF32_ST_TYPE(symp->st_info) != STT_OBJECT)
			return (ctf_set_errno(fp, ECTF_NOTDATA));
	} else {
		const Elf64_Sym *symp = (Elf64_Sym *)sp->cts_data + symidx;
		if (ELF64_ST_TYPE(symp->st_info) != STT_OBJECT)
			return (ctf_set_errno(fp, ECTF_NOTDATA));
	}

	if (fp->ctf_sxlate[symidx] == -1u)
		return (ctf_set_errno(fp, ECTF_NOTYPEDAT));

	type = *(ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]);
	if (type == 0)
		return (ctf_set_errno(fp, ECTF_NOTYPEDAT));

	return (type);
}
Exemple #6
0
int
pmelf_getsym64(Elf_Stream s, Elf64_Sym *psym)
{
	if ( 1 != SREAD(psym, sizeof(*psym), 1, s) ) {
		return -1;
	}
	if ( s->needswap ) {
#ifdef PMELF_CONFIG_NO_SWAPSUPPORT
		return -2;
#else
		elf_swap32( &psym->st_name);
		elf_swap16( &psym->st_shndx);
		elf_swap64( &psym->st_value);
		elf_swap64( &psym->st_size);
#endif
	}
#ifdef PARANOIA_ON
	{
	int x;
	if ( (x = ELF64_ST_TYPE( psym->st_info )) > STT_MAXSUP ) {
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_getsym - paranoia: unsupported type %i\n", x);
		return -1;
	}
	if ( (x = ELF64_ST_BIND( psym->st_info )) > STB_MAXSUP ) {
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_getsym - paranoia: unsupported binding %i\n", x);
		return -1;
	}
	}
#endif
	return 0;
}
Exemple #7
0
struct _list * elf64_entries (const struct _buffer * buffer)
{
    if (elf64_check(buffer))
        return NULL;

    Elf64_Ehdr * ehdr = elf64_ehdr(buffer);
    if (ehdr == NULL)
        return NULL;

    struct _list * entries = list_create();

    struct _index * index = index_create(ehdr->e_entry);
    list_append(entries, index);
    object_delete(index);

    size_t shdr_i;
    for (shdr_i = 0; shdr_i < ehdr->e_shnum; shdr_i++) {
        size_t sym_i = 0;
        Elf64_Sym * sym;
        while ((sym = elf64_sym(buffer, shdr_i, sym_i++)) != NULL) {
            if (    (ELF64_ST_TYPE(sym->st_info) == STT_FUNC)
                 && (sym->st_value != 0)) {
                struct _index * index = index_create(sym->st_value);
                list_append(entries, index);
                object_delete(index);
            }
        }
    }

    return entries;
}
Exemple #8
0
static int dls_get_external_syms(char *base, struct dls_external_symlist *out)
{
    dls_shdr *s4 = dls_get_shdr_by_name(base, ".dynsym");
    dls_shdr *s5 = dls_get_shdr_by_name(base, ".dynstr");
    int nr_sym = s4->sh_size / sizeof(dls_sym);
    int i, count;
    dls_shdr *first_section = (dls_shdr *)(base + ((dls_ehdr*)base)->e_shoff);

    char *u = base + s5->sh_offset;
    dls_sym *sym = (dls_sym *)(base + s4->sh_offset);
    out->des_array = malloc(sizeof(struct dls_external_sym) * nr_sym);
    out->des_len = 0;
    for(i = 0; i < nr_sym; ++i, ++sym) {
        if(ELF64_ST_BIND(sym->st_info) == 1 &&
           ELF64_ST_TYPE(sym->st_info) == 0) {
            out->des_array[out->des_len].de_sym  = sym;
            out->des_array[out->des_len].de_name = u + sym->st_name;
            out->des_array[out->des_len].de_rel  =
                    (void*)dls_get_rel_sym(base, s4 - first_section, i);
            out->des_len++; 
        }
    }
    out->des_array = realloc(out->des_array,
                             out->des_len * sizeof(struct dls_external_sym));
    return out->des_len;
}
uint64_t find_symbol(struct LKM_Module *lkm_mod, struct Secthdr *secthdr, struct Symhdr *symhdr, struct Elf64_Rela *rela)
{
	struct Symhdr *rela_sym = &symhdr[ELF64_R_SYM(rela->r_info)];
	char *str_tab = lkm_mod->st_table;
	uint64_t sym_val;
	int ret=0,ret2=0;
	switch(rela_sym->st_shndx){
		case ELF_SHN_UNDEF:
//			cprintf("Undefined Symbol:%s \n", (void *)((char *)lkm_mod->st_table + rela_sym->st_name));
			sym_val = fetch_symbol_addr(rela_sym->st_name +str_tab);
			if(sym_val == 0){
				cprintf("Unable to find %s(). Probably its Dependent on some Module which is not loaded.....\n",(void *)((char *)lkm_mod->st_table + rela_sym->st_name));
				return 0;
			}
			dependencies_tmp[dependent_count]=fetch_symbol_tag(rela_sym->st_name +str_tab);
			if(((ret = strncmp("kernel", dependencies_tmp[dependent_count], strlen("kernel"))) != 0) && ((ret2=strlen(dependencies_tmp[dependent_count]))!=0)){
//				cprintf("Symbol: %s Dependent on %s Dependent count = %d \n", rela_sym->st_name +str_tab, dependencies_tmp[dependent_count],dependent_count);
				lkm_mod->depd_count++;
				dependent_count++;
			}else{
				memset(dependencies_tmp[dependent_count],'\0', sizeof(dependencies_tmp[dependent_count]));
			}
			sym_val = sym_val + rela->r_addend;
			break;
		case ELF_SHN_ABS:
			sym_val = rela_sym->st_value;
			break;
		case ELF_SHN_COMMON:
			sym_val = 0;
			break;
		default:
			if(rela_sym->st_shndx > lkm_mod->elf_hdr->e_shnum){
				cprintf("Error while relocating..\n");
				return 0;
			}
			struct Secthdr *tmp_sect = &lkm_mod->sect_hdr[rela_sym->st_shndx];
			uint64_t addr;
			if(strcmp((lkm_mod->shname_st_table + tmp_sect->sh_name),".data") == 0){
				addr = (uint64_t)lkm_mod->data_addr;
			}else if(strcmp((lkm_mod->shname_st_table + tmp_sect->sh_name),".text") == 0){
				addr = (uint64_t)lkm_mod->text_addr;
			}else if(strcmp((lkm_mod->shname_st_table + tmp_sect->sh_name),".rodata") == 0){
				addr = (uint64_t)lkm_mod->rodata_addr;
			}else if(strcmp((lkm_mod->shname_st_table + tmp_sect->sh_name),".bss") == 0){
				addr = (uint64_t)lkm_mod->bss_addr;
			}
			sym_val = addr + rela_sym->st_value + rela->r_addend;
			if(ELF64_ST_TYPE(rela_sym->st_info) == STT_FUNC){
//				cprintf("symbol name is %s symbol value is %x \n",(str_tab + rela_sym->st_name), sym_val);
				if((ret = strncmp(str_tab + rela_sym->st_name, "lkm_init", strlen("lkm_init")) != 0) && (ret = strncmp(str_tab + rela_sym->st_name, "lkm_exit", strlen("lkm_exit")))!= 0){
					if((ret = strlen(str_tab + rela_sym->st_name)) != 0){	//new code
						insert_symbol(str_tab + rela_sym->st_name, sym_val, modules_lkm[mod_num].name);
					}
				}
			}
			break;
	}
	return sym_val;
}
Exemple #10
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));
}
Exemple #11
0
uintptr_t
la_symbind64(Elf64_Sym *sym, unsigned idx, uintptr_t *refcook,
	     uintptr_t *defcook, unsigned *flags, const char *symname)
{
	/* Don't try to interpose on non-function relocations */
	if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
		return sym->st_value;

	if (audit_this_function(symname))
		return (uintptr_t)allocate_trampoline(symname, (void *)sym->st_value);
	else
		return sym->st_value;
}
Exemple #12
0
/* Extract the list of source files, if present. The source files are
 * determined by loading the symbol table section (and its associated
 * string table) and looking up symbols of type STT_FILE.
 */
static int getsrcfiles(textline **plines)
{
    Elf64_Sym  *syms;
    char       *nmstr;
    textline   *lines;
    char       *str;
    unsigned	strtab, count, i;
    int		j, n;

    if (!secthdrs)
	return 0;
    for (i = 0 ; i < elffhdr.e_shnum ; ++i)
	if (secthdr[i].sh_type == SHT_SYMTAB)
	    break;
    if (i == elffhdr.e_shnum)
	return 0;

    count = secthdr[i].sh_size / secthdr[i].sh_entsize;
    strtab = secthdr[i].sh_link;
    if (!(syms = malloc(count * sizeof *syms)))
	nomem();
    if (fseek(thefile, secthdr[i].sh_offset, SEEK_SET))
	return err("%s: invalid symbol table offset.", thefilename);
    count = elfrw_read_Syms(thefile, syms, count);
    if (!count)
	return 0;
    nmstr = getarea(secthdr[strtab].sh_offset, secthdr[strtab].sh_size);
    if (!nmstr) {
	free(syms);
	return 0;
    }
    lines = gettextlines(count);
    n = 0;
    for (i = 0 ; i < count ; ++i) {
	if (ELF64_ST_TYPE(syms[i].st_info) != STT_FILE)
	    continue;
	str = nmstr + syms[i].st_name;
	for (j = 0 ; j < n ; ++j)
	    if (!strcmp(lines[j].str, str))
		break;
	if (j == n)
	    append(lines + n++, "%s", str);
    }
    free(syms);
    free(nmstr);
    if (n)
	*plines = lines;
    else
	free(lines);
    return n;
}
Exemple #13
0
static int _decode64_symtab(AsmFormatPlugin * format, Elf64_Ehdr * ehdr,
		Elf64_Shdr * shdr, size_t shdr_cnt, uint16_t ndx)
{
	AsmFormatPluginHelper * helper = format->helper;
	char * strtab = NULL;
	size_t strtab_cnt = 0;
	Elf64_Sym sym;
	size_t i;
	off_t offset;

#ifdef DEBUG
	fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif
	if(ndx >= shdr_cnt || shdr[ndx].sh_entsize != sizeof(sym))
		return -1;
	if(_decode64_strtab(format, shdr, shdr_cnt, shdr[ndx].sh_link, &strtab,
				&strtab_cnt) != 0)
		return -1;
	/* read and process symbols */
	if((offset = helper->seek(helper->format, shdr[ndx].sh_offset,
					SEEK_SET)) < 0
			|| (unsigned long)offset != shdr[ndx].sh_offset)
	{
		free(strtab);
		return -1;
	}
	for(i = 0; i * sizeof(sym) < shdr[ndx].sh_size; i++)
		if(helper->read(helper->format, &sym, sizeof(sym))
				!= sizeof(sym))
			break;
		else if(sym.st_name >= strtab_cnt)
			break;
		else if(ELF64_ST_TYPE(sym.st_info) == STT_FUNC)
		{
			offset = -1;
			if(ehdr->e_type == ET_REL || ehdr->e_type == ET_EXEC
					|| ehdr->e_type == ET_DYN)
				offset = sym.st_value;
			/* record the function */
			helper->set_function(helper->format, i,
					&strtab[sym.st_name], offset,
					sym.st_size);
		}
	if(i * sizeof(sym) != shdr[ndx].sh_size)
	{
		free(strtab);
		return -1;
	}
	return 0;
}
Exemple #14
0
/*
 * Sort comparison function for 64-bit symbol address-to-name lookups.  We sort
 * symbols by value.  If values are equal, we prefer the symbol that is
 * non-zero sized, typed, not weak, or lexically first, in that order.
 */
static int
dt_module_symcomp64(const void *lp, const void *rp)
{
	Elf64_Sym *lhs = *((Elf64_Sym **)lp);
	Elf64_Sym *rhs = *((Elf64_Sym **)rp);

	if (lhs->st_value != rhs->st_value)
		return (lhs->st_value > rhs->st_value ? 1 : -1);

	if ((lhs->st_size == 0) != (rhs->st_size == 0))
		return (lhs->st_size == 0 ? 1 : -1);

	if ((ELF64_ST_TYPE(lhs->st_info) == STT_NOTYPE) !=
	    (ELF64_ST_TYPE(rhs->st_info) == STT_NOTYPE))
		return (ELF64_ST_TYPE(lhs->st_info) == STT_NOTYPE ? 1 : -1);

	if ((ELF64_ST_BIND(lhs->st_info) == STB_WEAK) !=
	    (ELF64_ST_BIND(rhs->st_info) == STB_WEAK))
		return (ELF64_ST_BIND(lhs->st_info) == STB_WEAK ? 1 : -1);

	return (strcmp(dt_module_strtab + lhs->st_name,
	    dt_module_strtab + rhs->st_name));
}
Exemple #15
0
/*
 * Given a symbol table index, return the info for the function described
 * by the corresponding entry in the symbol table.
 */
int
ctf_func_info(ctf_file_t *fp, ulong_t symidx, ctf_funcinfo_t *fip)
{
	const ctf_sect_t *sp = &fp->ctf_symtab;
	const ushort_t *dp;
	ushort_t info, kind, n;

	if (sp->cts_data == NULL)
		return (ctf_set_errno(fp, ECTF_NOSYMTAB));

	if (symidx >= fp->ctf_nsyms)
		return (ctf_set_errno(fp, EINVAL));

	if (sp->cts_entsize == sizeof (Elf32_Sym)) {
		const Elf32_Sym *symp = (Elf32_Sym *)sp->cts_data + symidx;
		if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC)
			return (ctf_set_errno(fp, ECTF_NOTFUNC));
	} else {
		const Elf64_Sym *symp = (Elf64_Sym *)sp->cts_data + symidx;
		if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC)
			return (ctf_set_errno(fp, ECTF_NOTFUNC));
	}

	if (fp->ctf_sxlate[symidx] == -1u)
		return (ctf_set_errno(fp, ECTF_NOFUNCDAT));

	dp = (ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]);

	info = *dp++;
	kind = LCTF_INFO_KIND(fp, info);
	n = LCTF_INFO_VLEN(fp, info);

	if (kind == CTF_K_UNKNOWN && n == 0)
		return (ctf_set_errno(fp, ECTF_NOFUNCDAT));

	if (kind != CTF_K_FUNCTION)
		return (ctf_set_errno(fp, ECTF_CORRUPT));

	fip->ctc_return = *dp++;
	fip->ctc_argc = n;
	fip->ctc_flags = 0;

	if (n != 0 && dp[n - 1] == 0) {
		fip->ctc_flags |= CTF_FUNC_VARARG;
		fip->ctc_argc--;
	}

	return (0);
}
Exemple #16
0
static void	get_info_sym(Elf64_Sym *sym)
{
  int		info;
  int		bind;
  int		type;
  int		index;
  char		c;

  info = sym->st_info;
  bind = ELF64_ST_BIND(info);
  type = ELF64_ST_TYPE(info);
  index = sym->st_shndx;
  c = get_carac(index, type, bind);
  printf("%c ", c);
}
Exemple #17
0
static uint_t
dt_module_syminit64(dt_module_t *dmp)
{
#if STT_NUM != (STT_TLS + 1)
#error "STT_NUM has grown. update dt_module_syminit64()"
#endif

	Elf64_Sym *sym = dmp->dm_symtab.cts_data;
	const char *base = dmp->dm_strtab.cts_data;
	size_t ss_size = dmp->dm_strtab.cts_size;
	uint_t i, n = dmp->dm_nsymelems;
	uint_t asrsv = 0;

#if defined(__FreeBSD__)
	GElf_Ehdr ehdr;
	int is_elf_obj;

	gelf_getehdr(dmp->dm_elf, &ehdr);
	is_elf_obj = (ehdr.e_type == ET_REL);
#endif

	for (i = 0; i < n; i++, sym++) {
		const char *name = base + sym->st_name;
		uchar_t type = ELF64_ST_TYPE(sym->st_info);

		if (type >= STT_NUM || type == STT_SECTION)
			continue; /* skip sections and unknown types */

		if (sym->st_name == 0 || sym->st_name >= ss_size)
			continue; /* skip null or invalid names */

		if (sym->st_value != 0 &&
		    (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
			asrsv++; /* reserve space in the address map */
#if defined(__FreeBSD__)
			sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
			if (is_elf_obj && sym->st_shndx != SHN_UNDEF &&
			    sym->st_shndx < ehdr.e_shnum)
				sym->st_value +=
				    dmp->dm_sec_offsets[sym->st_shndx];
#endif
		}

		dt_module_symhash_insert(dmp, name, i);
	}

	return (asrsv);
}
Exemple #18
0
static void	display_symbol(t_dumper *dumper, Elf64_Sym *sym)
{
  const char	*name;
  char		type;
  Elf64_Shdr	*shdr;

  name = dumper_get_sym_name(dumper, sym);
  shdr = dumper_get_shdr_by_index(dumper, sym->st_shndx);
  type = get_symbol_type(dumper, sym);
  if (name[0] == '\0' || ELF64_ST_TYPE(sym->st_info) == STT_FILE)
    return ;
  if (type == 'U' || type == 'w')
    printf("%s", "                ");
  else
    printf("%016lx", sym->st_value);
  printf(" %c %s\n", type, name);
}
Exemple #19
0
static void
assign64(void *symp, CexpSym cesp, void *closure)
{
Elf64_Sym	*sp=symp;
CexpType	t;
int 		s=sp->st_size;

	cesp->size = s;

	t=TVoid;

	switch (ELF64_ST_TYPE(sp->st_info)) {
	case STT_OBJECT:
		/* determine the type of variable */
		t = cexpTypeGuessFromSize(s);
	break;

	case STT_FUNC:
		t=TFuncP;
	break;

	case STT_NOTYPE:
		t=TVoid;
	break;

	case STT_SECTION:
		t=TVoid;
		cesp->flags|=CEXP_SYMFLG_SECT;
	break;

	default:
	break;

	}

	cesp->value.type = t;

	switch(ELF64_ST_BIND(sp->st_info)) {
		case STB_GLOBAL: cesp->flags|=CEXP_SYMFLG_GLBL; break;
		case STB_WEAK  : cesp->flags|=CEXP_SYMFLG_WEAK; break;
		default:
			break;
	}

	cesp->value.ptv  = (CexpVal)(uintptr_t)sp->st_value;
}
char *symbol_type(unsigned char st_info)
{
    switch (ELF64_ST_TYPE(st_info)) {
    case STT_NOTYPE: return "STT_NOTYPE";
    case STT_OBJECT: return "STT_OBJECT";
    case STT_FUNC: return "STT_FUNC";
    case STT_SECTION: return "STT_SECTION";
    case STT_FILE: return "STT_FILE";
    case STT_COMMON: return "STT_COMMON";
    case STT_TLS: return "STT_TLS";
    case STT_NUM: return "STT_NUM";
    case STT_LOOS: return "STT_LOOS STT_GNU_IFUNC";
    case STT_HIOS: return "STT_HIOS";
    case STT_LOPROC: return "STT_LOPROC";
    case STT_HIPROC: return "STT_HIPROC";
    default: return "unknown";
    }
}
static U8_T get_elf_symbol_address(Elf_Sym * x) {
    if (sCache->mFile->elf64) {
        Elf64_Sym * s = (Elf64_Sym *)x;
        switch (ELF64_ST_TYPE(s->st_info)) {
        case STT_OBJECT:
        case STT_FUNC:
            return s->st_value;
        }
    }
    else {
        Elf32_Sym * s = (Elf32_Sym *)x;
        switch (ELF32_ST_TYPE(s->st_info)) {
        case STT_OBJECT:
        case STT_FUNC:
            return s->st_value;
        }
    }
    return 0;
}
Exemple #22
0
const char * elf64_label (const struct _buffer * buffer, uint64_t address)
{
    size_t shdr_i;
    Elf64_Shdr * shdr;

    for (shdr_i = 0; (shdr = elf64_shdr(buffer, shdr_i)) != NULL; shdr_i++) {
        size_t sym_i;
        Elf64_Sym * sym;
        for (sym_i = 0; (sym = elf64_sym(buffer, shdr_i, sym_i)) != NULL; sym_i++) {
            if (    (ELF64_ST_TYPE(sym->st_info) == STT_FUNC)
                 && (sym->st_value == address)) {
                const char * symbol = elf64_strtab(buffer, shdr->sh_link, sym->st_name);
                if (symbol != NULL)
                    return symbol;
            }
        }
    }

    return NULL;
}
Exemple #23
0
bool		print(Elf64_Sym **tab, char *strtab)
{
  int		i;

  i = 0;
  while (tab[i])
    {
      if (ELF64_ST_TYPE(tab[i]->st_info) != STT_FILE)
	{
	  if (tab[i]->st_value)
	    printf("%016x ", (unsigned int)tab[i]->st_value);
	  else
	    printf("\t\t ");
	  get_info_sym(tab[i]);
	  printf("%s\n", strtab + tab[i]->st_name);
	}
      i++;
    }
  return (true);
}
Exemple #24
0
static const char *
filter64(void *ext_sym, void *closure)
{
Elf64_Sym	*sp=ext_sym;
char		*strtab=closure;

	if ( STB_LOCAL == ELF64_ST_BIND(sp->st_info) )
		return 0;

	switch (ELF64_ST_TYPE(sp->st_info)) {
	case STT_OBJECT:
	case STT_FUNC:
	case STT_NOTYPE:
	return strtab + sp->st_name;

	default:
	break;
	}

	return 0;
}
Exemple #25
0
/*
 * Initialize the symtab translation table by filling each entry with the
 * offset of the CTF type or function data corresponding to each STT_FUNC or
 * STT_OBJECT entry in the symbol table.
 */
static int
init_symtab(ctf_file_t *fp, const ctf_header_t *hp,
    const ctf_sect_t *sp, const ctf_sect_t *strp)
{
	const uchar_t *symp = sp->cts_data;
	uint_t *xp = fp->ctf_sxlate;
	uint_t *xend = xp + fp->ctf_nsyms;

	uint_t objtoff = hp->cth_objtoff;
	uint_t funcoff = hp->cth_funcoff;

	ushort_t info, vlen;
	Elf64_Sym sym, *gsp;
	const char *name;

	/*
	 * The CTF data object and function type sections are ordered to match
	 * the relative order of the respective symbol types in the symtab.
	 * If no type information is available for a symbol table entry, a
	 * pad is inserted in the CTF section.  As a further optimization,
	 * anonymous or undefined symbols are omitted from the CTF data.
	 */
	for (; xp < xend; xp++, symp += sp->cts_entsize) {
		if (sp->cts_entsize == sizeof (struct nlist)) {
			gsp = sym_to_gelf_macho(sp, (Elf32_Sym *)(uintptr_t)symp, &sym, (const char *)strp->cts_data);
		}
		else if (sp->cts_entsize == sizeof (struct nlist_64)) {
			gsp = sym_to_gelf_macho_64(sp, (Elf32_Sym *)(uintptr_t)symp, &sym, (const char *)strp->cts_data);
		}
		else if (sp->cts_entsize == sizeof (Elf32_Sym))
			gsp = sym_to_gelf((Elf32_Sym *)(uintptr_t)symp, &sym);
		else
			gsp = (Elf64_Sym *)(uintptr_t)symp;

		if (gsp->st_name < strp->cts_size)
			name = (const char *)strp->cts_data + gsp->st_name;
		else
			name = _CTF_NULLSTR;

		if (gsp->st_name == 0 || gsp->st_shndx == SHN_UNDEF ||
		    strcmp(name, "_START_") == 0 ||
		    strcmp(name, "_END_") == 0) {
			*xp = -1u;
			continue;
		}

		switch (ELF64_ST_TYPE(gsp->st_info)) {
		case STT_OBJECT:
			if (objtoff >= hp->cth_funcoff ||
			    (gsp->st_shndx == SHN_ABS && gsp->st_value == 0)) {
				*xp = -1u;
				break;
			}

			*xp = objtoff;
			objtoff += sizeof (ushort_t);
			break;

		case STT_FUNC:
			if (funcoff >= hp->cth_typeoff) {
				*xp = -1u;
				break;
			}

			*xp = funcoff;

			info = *(ushort_t *)((uintptr_t)fp->ctf_buf + funcoff);
			vlen = LCTF_INFO_VLEN(fp, info);

			/*
			 * If we encounter a zero pad at the end, just skip it.
			 * Otherwise skip over the function and its return type
			 * (+2) and the argument list (vlen).
			 */
			if (LCTF_INFO_KIND(fp, info) == CTF_K_UNKNOWN &&
			    vlen == 0)
				funcoff += sizeof (ushort_t); /* skip pad */
			else
				funcoff += sizeof (ushort_t) * (vlen + 2);
			break;

		default:
			*xp = -1u;
			break;
		}
	}

	ctf_dprintf("loaded %lu symtab entries\n", fp->ctf_nsyms);
	return (0);
}
Exemple #26
0
int vdso_fill_symtable(char *mem, size_t size, struct vdso_symtable *t)
{
	Elf64_Phdr *dynamic = NULL, *load = NULL;
	Elf64_Ehdr *ehdr = (void *)mem;
	Elf64_Dyn *dyn_strtab = NULL;
	Elf64_Dyn *dyn_symtab = NULL;
	Elf64_Dyn *dyn_strsz = NULL;
	Elf64_Dyn *dyn_syment = NULL;
	Elf64_Dyn *dyn_hash = NULL;
	Elf64_Word *hash = NULL;
	Elf64_Phdr *phdr;
	Elf64_Dyn *d;

	Elf64_Word *bucket, *chain;
	Elf64_Word nbucket, nchain;

	/*
	 * See Elf specification for this magic values.
	 */
	static const char elf_ident[] = {
		0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	};

	char *dynsymbol_names;
	unsigned int i, j, k;

	BUILD_BUG_ON(sizeof(elf_ident) != sizeof(ehdr->e_ident));

	pr_debug("Parsing at %lx %lx\n", (long)mem, (long)mem + (long)size);

	/*
	 * Make sure it's a file we support.
	 */
	if (builtin_memcmp(ehdr->e_ident, elf_ident, sizeof(elf_ident))) {
		pr_err("Elf header magic mismatch\n");
		return -EINVAL;
	}

	/*
	 * We need PT_LOAD and PT_DYNAMIC here. Each once.
	 */
	phdr = (void *)&mem[ehdr->e_phoff];
	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
		if (__ptr_oob(phdr, mem, size))
			goto err_oob;
		switch (phdr->p_type) {
		case PT_DYNAMIC:
			if (dynamic) {
				pr_err("Second PT_DYNAMIC header\n");
				return -EINVAL;
			}
			dynamic = phdr;
			break;
		case PT_LOAD:
			if (load) {
				pr_err("Second PT_LOAD header\n");
				return -EINVAL;
			}
			load = phdr;
			break;
		}
	}

	if (!load || !dynamic) {
		pr_err("One of obligated program headers is missed\n");
		return -EINVAL;
	}

	pr_debug("PT_LOAD p_vaddr: %lx\n", (unsigned long)load->p_vaddr);

	/*
	 * Dynamic section tags should provide us the rest of information
	 * needed. Note that we're interested in a small set of tags.
	 */
	d = (void *)&mem[dynamic->p_offset];
	for (i = 0; i < dynamic->p_filesz / sizeof(*d); i++, d++) {
		if (__ptr_oob(d, mem, size))
			goto err_oob;

		if (d->d_tag == DT_NULL) {
			break;
		} else if (d->d_tag == DT_STRTAB) {
			dyn_strtab = d;
			pr_debug("DT_STRTAB: %lx\n", (unsigned long)d->d_un.d_ptr);
		} else if (d->d_tag == DT_SYMTAB) {
			dyn_symtab = d;
			pr_debug("DT_SYMTAB: %lx\n", (unsigned long)d->d_un.d_ptr);
		} else if (d->d_tag == DT_STRSZ) {
			dyn_strsz = d;
			pr_debug("DT_STRSZ: %lx\n", (unsigned long)d->d_un.d_val);
		} else if (d->d_tag == DT_SYMENT) {
			dyn_syment = d;
			pr_debug("DT_SYMENT: %lx\n", (unsigned long)d->d_un.d_val);
		} else if (d->d_tag == DT_HASH) {
			dyn_hash = d;
			pr_debug("DT_HASH: %lx\n", (unsigned long)d->d_un.d_ptr);
		}
	}

	if (!dyn_strtab || !dyn_symtab || !dyn_strsz || !dyn_syment || !dyn_hash) {
		pr_err("Not all dynamic entries are present\n");
		return -EINVAL;
	}

	dynsymbol_names = &mem[dyn_strtab->d_un.d_val - load->p_vaddr];
	if (__ptr_oob(dynsymbol_names, mem, size))
		goto err_oob;

	hash = (void *)&mem[(unsigned long)dyn_hash->d_un.d_ptr - (unsigned long)load->p_vaddr];
	if (__ptr_oob(hash, mem, size))
		goto err_oob;

	nbucket = hash[0];
	nchain = hash[1];
	bucket = &hash[2];
	chain = &hash[nbucket + 2];

	pr_debug("nbucket %lx nchain %lx bucket %lx chain %lx\n",
		 (long)nbucket, (long)nchain, (unsigned long)bucket, (unsigned long)chain);

	for (i = 0; i < VDSO_SYMBOL_MAX; i++) {
		const char * symbol = vdso_symbols[i];
		k = elf_hash((const unsigned char *)symbol);

		for (j = bucket[k % nbucket]; j < nchain && chain[j] != STN_UNDEF; j = chain[j]) {
			Elf64_Sym *sym = (void *)&mem[dyn_symtab->d_un.d_ptr - load->p_vaddr];
			char *name;

			sym = &sym[j];
			if (__ptr_oob(sym, mem, size))
				continue;

			if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC &&
			    ELF64_ST_BIND(sym->st_info) != STB_GLOBAL)
				continue;

			name = &dynsymbol_names[sym->st_name];
			if (__ptr_oob(name, mem, size))
				continue;

			if (builtin_strcmp(name, symbol))
				continue;

			builtin_memcpy(t->symbols[i].name, name, sizeof(t->symbols[i].name));
			t->symbols[i].offset = (unsigned long)sym->st_value - load->p_vaddr;
			break;
		}
	}

	return 0;

err_oob:
	pr_err("Corrupted Elf data\n");
	return -EFAULT;
}
Exemple #27
0
STATIC
BOOLEAN
WriteSections64 (
  SECTION_FILTER_TYPES  FilterType
  )
{
  UINT32      Idx;
  Elf_Shdr    *SecShdr;
  UINT32      SecOffset;
  BOOLEAN     (*Filter)(Elf_Shdr *);

  //
  // Initialize filter pointer
  //
  switch (FilterType) {
    case SECTION_TEXT:
      Filter = IsTextShdr;
      break;
    case SECTION_HII:
      Filter = IsHiiRsrcShdr;
      break;
    case SECTION_DATA:
      Filter = IsDataShdr;
      break;
    default:
      return FALSE;
  }

  //
  // First: copy sections.
  //
  for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {
    Elf_Shdr *Shdr = GetShdrByIndex(Idx);
    if ((*Filter)(Shdr)) {
      switch (Shdr->sh_type) {
      case SHT_PROGBITS:
        /* Copy.  */
        memcpy(mCoffFile + mCoffSectionsOffset[Idx],
              (UINT8*)mEhdr + Shdr->sh_offset,
              (size_t) Shdr->sh_size);
        break;

      case SHT_NOBITS:
        memset(mCoffFile + mCoffSectionsOffset[Idx], 0, (size_t) Shdr->sh_size);
        break;

      default:
        //
        //  Ignore for unkown section type.
        //
        VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type);
        break;
      }
    }
  }

  //
  // Second: apply relocations.
  //
  VerboseMsg ("Applying Relocations...");
  for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) {
    //
    // Determine if this is a relocation section.
    //
    Elf_Shdr *RelShdr = GetShdrByIndex(Idx);
    if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) {
      continue;
    }

    //
    // Relocation section found.  Now extract section information that the relocations
    // apply to in the ELF data and the new COFF data.
    //
    SecShdr = GetShdrByIndex(RelShdr->sh_info);
    SecOffset = mCoffSectionsOffset[RelShdr->sh_info];

    //
    // Only process relocations for the current filter type.
    //
    if (RelShdr->sh_type == SHT_RELA && (*Filter)(SecShdr)) {
      UINT64 RelIdx;

      //
      // Determine the symbol table referenced by the relocation data.
      //
      Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);
      UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset;

      //
      // Process all relocation entries for this section.
      //
      for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += (UINT32) RelShdr->sh_entsize) {

        //
        // Set pointer to relocation entry
        //
        Elf_Rela *Rel = (Elf_Rela *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx);

        //
        // Set pointer to symbol table entry associated with the relocation entry.
        //
        Elf_Sym  *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);

        Elf_Shdr *SymShdr;
        UINT8    *Targ;

        //
        // Check section header index found in symbol table and get the section
        // header location.
        //
        if (Sym->st_shndx == SHN_UNDEF
            || Sym->st_shndx == SHN_ABS
            || Sym->st_shndx > mEhdr->e_shnum) {
          Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName);
        }
        SymShdr = GetShdrByIndex(Sym->st_shndx);

        //
        // Convert the relocation data to a pointer into the coff file.
        //
        // Note:
        //   r_offset is the virtual address of the storage unit to be relocated.
        //   sh_addr is the virtual address for the base of the section.
        //
        //   r_offset in a memory address.
        //   Convert it to a pointer in the coff file.
        //
        Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);

        //
        // Determine how to handle each relocation type based on the machine type.
        //
        if (mEhdr->e_machine == EM_X86_64) {
          switch (ELF_R_TYPE(Rel->r_info)) {
          case R_X86_64_NONE:
            break;
          case R_X86_64_64:
            //
            // Absolute relocation.
            //
            VerboseMsg ("R_X86_64_64");
            VerboseMsg ("Offset: 0x%08X, Addend: 0x%016LX", 
              (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), 
              *(UINT64 *)Targ);
            *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];
            VerboseMsg ("Relocation:  0x%016LX", *(UINT64*)Targ);
            break;
          case R_X86_64_32:
            VerboseMsg ("R_X86_64_32");
            VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", 
              (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), 
              *(UINT32 *)Targ);
            *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);
            VerboseMsg ("Relocation:  0x%08X", *(UINT32*)Targ);
            break;
          case R_X86_64_32S:
            VerboseMsg ("R_X86_64_32S");
            VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", 
              (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), 
              *(UINT32 *)Targ);
            *(INT32 *)Targ = (INT32)((INT64)(*(INT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);
            VerboseMsg ("Relocation:  0x%08X", *(UINT32*)Targ);
            break;
          case R_X86_64_PC32:
            //
            // Relative relocation: Symbol - Ip + Addend
            //
            VerboseMsg ("R_X86_64_PC32");
            VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", 
              (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), 
              *(UINT32 *)Targ);
            *(UINT32 *)Targ = (UINT32) (*(UINT32 *)Targ
              + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)
              - (SecOffset - SecShdr->sh_addr));
            VerboseMsg ("Relocation:  0x%08X", *(UINT32 *)Targ);
            break;
          default:
            Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));
          }
        } else if (mEhdr->e_machine == EM_AARCH64) {

          // AARCH64 GCC uses RELA relocation, so all relocations have to be fixed up.
          // As opposed to ARM32 using REL.

          switch (ELF_R_TYPE(Rel->r_info)) {

          case R_AARCH64_ADR_PREL_LO21:
            if  (Rel->r_addend != 0 ) { /* TODO */
              Error (NULL, 0, 3000, "Invalid", "AArch64: R_AARCH64_ADR_PREL_LO21 Need to fixup with addend!.");
            }
            break;

          case R_AARCH64_CONDBR19:
            if  (Rel->r_addend != 0 ) { /* TODO */
              Error (NULL, 0, 3000, "Invalid", "AArch64: R_AARCH64_CONDBR19 Need to fixup with addend!.");
            }
            break;

          case R_AARCH64_LD_PREL_LO19:
            if  (Rel->r_addend != 0 ) { /* TODO */
              Error (NULL, 0, 3000, "Invalid", "AArch64: R_AARCH64_LD_PREL_LO19 Need to fixup with addend!.");
            }
            break;

          case R_AARCH64_CALL26:
          case R_AARCH64_JUMP26:
            if  (Rel->r_addend != 0 ) {
              // Some references to static functions sometime start at the base of .text + addend.
              // It is safe to ignore these relocations because they patch a `BL` instructions that
              // contains an offset from the instruction itself and there is only a single .text section.
              // So we check if the symbol is a "section symbol"
              if (ELF64_ST_TYPE (Sym->st_info) == STT_SECTION) {
                break;
              }
              Error (NULL, 0, 3000, "Invalid", "AArch64: R_AARCH64_JUMP26 Need to fixup with addend!.");
            }
            break;

          case R_AARCH64_ADR_PREL_PG_HI21:
            // TODO : AArch64 'small' memory model.
            Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_AARCH64 relocation R_AARCH64_ADR_PREL_PG_HI21.", mInImageName);
            break;

          case R_AARCH64_ADD_ABS_LO12_NC:
            // TODO : AArch64 'small' memory model.
            Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_AARCH64 relocation R_AARCH64_ADD_ABS_LO12_NC.", mInImageName);
            break;

          // Absolute relocations.
          case R_AARCH64_ABS64:
            *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];
            break;

          default:
            Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));
          }
        } else {
          Error (NULL, 0, 3000, "Invalid", "Not a supported machine type");
        }
      }
    }
  }

  return TRUE;
}
Exemple #28
0
int main(int argc, char* argv[]) {
	if(argc < 3) {
		printf("Usage: smap [kernel elf] [system map]\n");
		return 0;
	}
	
	int fd = open(argv[1], O_RDONLY);
	if(fd < 0) {
		printf("Cannot open file: %s\n", argv[1]);
		return 1;
	}
	
	struct stat state;
	if(stat(argv[1], &state) != 0) {
		printf("Cannot get state of file: %s\n", argv[1]);
		return 2;
	}
	
	Elf64_Ehdr* ehdr = mmap(NULL, state.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	if(ehdr == (void*)-1) {
		printf("Cannot open file: %s\n", argv[1]);
		return 1;
	}
	
	if(ehdr->e_ident[0] != ELFMAG0 || ehdr->e_ident[1] != ELFMAG1 || ehdr->e_ident[2] != ELFMAG2 || ehdr->e_ident[3] != ELFMAG3) {
		printf("Illegal file format: %s\n", argv[1]);
		return 3;
	}
	
	Elf64_Shdr* shdr = (Elf64_Shdr*)((uint8_t*)ehdr + ehdr->e_shoff);
	char* strs = (char*)ehdr + shdr[ehdr->e_shstrndx].sh_offset;
	Elf64_Shdr* get_shdr(char* name) {
		for(int i = 0; i < ehdr->e_shnum; i++) {
			if(strcmp(name, strs + shdr[i].sh_name) == 0)
				return &shdr[i];
		}
		return NULL;
	}
	
	Elf64_Shdr* strtab = get_shdr(".strtab");
	char* str = (char*)ehdr + strtab->sh_offset;
	char* name(int offset) {
		return str + offset;
	}
	
	int count = 0;
	int text_size = 0;
	
	Elf64_Shdr* symtab = get_shdr(".symtab");
	Elf64_Sym* sym = (void*)ehdr + symtab->sh_offset;
	int size = symtab->sh_size / sizeof(Elf64_Sym);
	for(int i = 0; i < size; i++) {
		if(ELF64_ST_BIND(sym[i].st_info) != STB_GLOBAL)
			continue;
		
		int type = ELF64_ST_TYPE(sym[i].st_info);
		switch(type) {
			case STT_NOTYPE:
			case STT_OBJECT:
			case STT_FUNC:
				break;
			default:
				printf("Unknown symbol type: %d for %s\n", type, name(sym[i].st_name));
				return 4;
		}
		
		count++;
		text_size += strlen(name(sym[i].st_name)) + 1;
	}
	
	// Make data structure
	int total = sizeof(Symbol) * (count + 1) + text_size;
	Symbol* symbols = malloc(total);
	char* text = (void*)symbols + total - text_size;
	int j = 0;
	for(int i = 0; i < size; i++) {
		if(ELF64_ST_BIND(sym[i].st_info) != STB_GLOBAL)
			continue;
		
		int type = ELF64_ST_TYPE(sym[i].st_info);
		switch(type) {
			case STT_NOTYPE:
				type = SYMBOL_TYPE_NONE;
				break;
			case STT_OBJECT:
				type = SYMBOL_TYPE_DATA;
				break;
			case STT_FUNC:
				type = SYMBOL_TYPE_FUNC;
				break;
			default:
				;// Not possible
		}
		
		symbols[j].name = (void*)((void*)text - (void*)symbols);
		symbols[j].type = type;
		symbols[j].address = (void*)(uint64_t)sym[i].st_value;
		j++;
		
		char* symname = name(sym[i].st_name);
		int len = strlen(symname) + 1;
		memcpy(text, symname, len);
		text += len;
	}
	close(fd);
	
	// Write
	int fd2 = open(argv[2], O_RDWR | O_CREAT, 0644);
	if(fd2 < 0) {
		printf("Cannot open file: %s\n", argv[2]);
		return 1;
	}
	
	// Write symbols
	int len = write(fd2, symbols, total);
	if(len != total) {
		printf("Cannot write fully: %d < %d\n", len, total);
		return 5;
	}
	
	close(fd2);
	
	return 0;
}
Exemple #29
0
void _mapFuncNames(ThreadContext *context, FileSys::SeekableDescription *fdesc, VAddr addr, size_t len, off_t off){
  typedef typename ElfDefs<mode>::Elf_Ehdr Elf_Ehdr;
  typedef typename ElfDefs<mode>::Elf_Shdr Elf_Shdr;
  typedef typename ElfDefs<mode>::Elf_Sym  Elf_Sym;
  // Read in the ELF header
  Elf_Ehdr ehdr;
  ssize_t ehdrSiz=fdesc->pread(&ehdr,sizeof(Elf_Ehdr),0);
  I(ehdrSiz==sizeof(Elf_Ehdr));
  cvtEndianEhdr<mode>(ehdr);
  // Read in section headers
  Elf_Shdr shdrs[ehdr.e_shnum];
  ssize_t shdrsSiz=fdesc->pread(shdrs,sizeof(Elf_Shdr)*ehdr.e_shnum,ehdr.e_shoff);
  I(shdrsSiz==(ssize_t)(sizeof(Elf_Shdr)*ehdr.e_shnum));
  I(shdrsSiz==(ssize_t)(sizeof(shdrs)));
  for(size_t sec=0;sec<ehdr.e_shnum;sec++)
    cvtEndianShdr<mode>(shdrs[sec]);
  // Read in section name strings
  I((ehdr.e_shstrndx>0)&&(ehdr.e_shstrndx<ehdr.e_shnum));
  char secStrTab[shdrs[ehdr.e_shstrndx].sh_size];
  ssize_t secStrTabSiz=fdesc->pread(secStrTab,shdrs[ehdr.e_shstrndx].sh_size,shdrs[ehdr.e_shstrndx].sh_offset);
  I(secStrTabSiz==(ssize_t)(shdrs[ehdr.e_shstrndx].sh_size));
  // Iterate over all sections
  for(size_t sec=0;sec<ehdr.e_shnum;sec++){
    switch(shdrs[sec].sh_type){
    case SHT_PROGBITS: {
      if(!(shdrs[sec].sh_flags&SHF_EXECINSTR))
        break;
      ssize_t loadBias=(addr-shdrs[sec].sh_addr)+(shdrs[sec].sh_offset-off);
      char  *secNam=secStrTab+shdrs[sec].sh_name;
      size_t secNamLen=strlen(secNam);
      if((off_t(shdrs[sec].sh_offset)>=off)&&(shdrs[sec].sh_offset<off+len)){
        char  *begNam="SecBeg";
        size_t begNamLen=strlen(begNam);
        char symNam[secNamLen+begNamLen+1];
        strcpy(symNam,begNam);
        strcpy(symNam+begNamLen,secNam);
        VAddr symAddr=shdrs[sec].sh_addr+loadBias;
        context->getAddressSpace()->addFuncName(symAddr,symNam,fdesc->getName());
      }
      if((off_t(shdrs[sec].sh_offset+shdrs[sec].sh_size)>off)&&
         (shdrs[sec].sh_offset+shdrs[sec].sh_size<=off+len)){
        char  *endNam="SecEnd";
        size_t endNamLen=strlen(endNam);
        char symNam[secNamLen+endNamLen+1];
        strcpy(symNam,endNam);
        strcpy(symNam+endNamLen,secNam);
        VAddr symAddr=shdrs[sec].sh_addr+shdrs[sec].sh_size+loadBias;
        context->getAddressSpace()->addFuncName(symAddr,symNam,fdesc->getName());
      }
    } break;
    case SHT_SYMTAB:
    case SHT_DYNSYM: {
      I(shdrs[sec].sh_entsize==sizeof(Elf_Sym));
      // Read in the symbols
      size_t symnum=shdrs[sec].sh_size/sizeof(Elf_Sym);
      Elf_Sym syms[symnum];
      ssize_t symsSiz=fdesc->pread(syms,shdrs[sec].sh_size,shdrs[sec].sh_offset);
      I(symsSiz==(ssize_t)(sizeof(Elf_Sym)*symnum));
      I(symsSiz==(ssize_t)(sizeof(syms)));
      for(size_t sym=0;sym<symnum;sym++)
        cvtEndianSym<mode>(syms[sym]);
      // Read in the symbol name strings
      char strTab[shdrs[shdrs[sec].sh_link].sh_size];
      ssize_t strTabSiz=fdesc->pread(strTab,shdrs[shdrs[sec].sh_link].sh_size,shdrs[shdrs[sec].sh_link].sh_offset);
      I(strTabSiz==(ssize_t)(shdrs[shdrs[sec].sh_link].sh_size));
      for(size_t sym=0;sym<symnum;sym++){
        I(ELF32_ST_TYPE(syms[sym].st_info)==ELF64_ST_TYPE(syms[sym].st_info));
        switch(ELF64_ST_TYPE(syms[sym].st_info)){
        case STT_FUNC: {
          if(!syms[sym].st_shndx)
            break;
          ssize_t loadBias=(addr-shdrs[syms[sym].st_shndx].sh_addr)+
                           (shdrs[syms[sym].st_shndx].sh_offset-off);
//          printf("sh_type %s st_name %s st_value 0x%08x st_size 0x%08x st_shndx 0x%08x\n",
//                 shdrs[sec].sh_type==SHT_SYMTAB?"SYMTAB":"DYNSYM",
//                 strTab+syms[sym].st_name,
//                 (int)(syms[sym].st_value),(int)(syms[sym].st_size),(int)(syms[sym].st_shndx));
          char *symNam=strTab+syms[sym].st_name;
          VAddr symAddr=syms[sym].st_value+loadBias;
          if((symAddr<addr)||(symAddr>=addr+len))
            break;
	  context->getAddressSpace()->addFuncName(symAddr,symNam,fdesc->getName());
        }  break;
        }
      }
    }  break;
    }
  }
}
Exemple #30
0
int
apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab,
           unsigned int symindex, unsigned int relsec,
           struct module *me)
{
    Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;
    unsigned long i, n = sechdrs[relsec].sh_size / sizeof(*rela);
    Elf64_Sym *symtab, *sym;
    void *base, *location;
    unsigned long got, gp;

    DEBUGP("Applying relocate section %u to %u\n", relsec,
           sechdrs[relsec].sh_info);

    base = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr;
    symtab = (Elf64_Sym *)sechdrs[symindex].sh_addr;

    /* The small sections were sorted to the end of the segment.
       The following should definitely cover them.  */
    gp = (u64)me->module_core + me->core_size - 0x8000;
    got = sechdrs[me->arch.gotsecindex].sh_addr;

    for (i = 0; i < n; i++) {
        unsigned long r_sym = ELF64_R_SYM (rela[i].r_info);
        unsigned long r_type = ELF64_R_TYPE (rela[i].r_info);
        unsigned long r_got_offset = r_type >> 8;
        unsigned long value, hi, lo;
        r_type &= 0xff;

        /* This is where to make the change.  */
        location = base + rela[i].r_offset;

        /* This is the symbol it is referring to.  Note that all
           unresolved symbols have been resolved.  */
        sym = symtab + r_sym;
        value = sym->st_value + rela[i].r_addend;

        switch (r_type) {
        case R_ALPHA_NONE:
            break;
        case R_ALPHA_REFQUAD:
            /* BUG() can produce misaligned relocations. */
            ((u32 *)location)[0] = value;
            ((u32 *)location)[1] = value >> 32;
            break;
        case R_ALPHA_GPREL32:
            value -= gp;
            if ((int)value != value)
                goto reloc_overflow;
            *(u32 *)location = value;
            break;
        case R_ALPHA_LITERAL:
            hi = got + r_got_offset;
            lo = hi - gp;
            if ((short)lo != lo)
                goto reloc_overflow;
            *(u16 *)location = lo;
            *(u64 *)hi = value;
            break;
        case R_ALPHA_LITUSE:
            break;
        case R_ALPHA_GPDISP:
            value = gp - (u64)location;
            lo = (short)value;
            hi = (int)(value - lo);
            if (hi + lo != value)
                goto reloc_overflow;
            *(u16 *)location = hi >> 16;
            *(u16 *)(location + rela[i].r_addend) = lo;
            break;
        case R_ALPHA_BRSGP:
            /* BRSGP is only allowed to bind to local symbols.
               If the section is undef, this means that the
               value was resolved from somewhere else.  */
            if (sym->st_shndx == SHN_UNDEF)
                goto reloc_overflow;
            if ((sym->st_other & STO_ALPHA_STD_GPLOAD) ==
                STO_ALPHA_STD_GPLOAD)
                /* Omit the prologue. */
                value += 8;
            /* FALLTHRU */
        case R_ALPHA_BRADDR:
            value -= (u64)location + 4;
            if (value & 3)
                goto reloc_overflow;
            value = (long)value >> 2;
            if (value + (1<<21) >= 1<<22)
                goto reloc_overflow;
            value &= 0x1fffff;
            value |= *(u32 *)location & ~0x1fffff;
            *(u32 *)location = value;
            break;
        case R_ALPHA_HINT:
            break;
        case R_ALPHA_SREL32:
            value -= (u64)location;
            if ((int)value != value)
                goto reloc_overflow;
            *(u32 *)location = value;
            break;
        case R_ALPHA_SREL64:
            value -= (u64)location;
            *(u64 *)location = value;
            break;
        case R_ALPHA_GPRELHIGH:
            value = (long)(value - gp + 0x8000) >> 16;
            if ((short) value != value)
                goto reloc_overflow;
            *(u16 *)location = value;
            break;
        case R_ALPHA_GPRELLOW:
            value -= gp;
            *(u16 *)location = value;
            break;
        case R_ALPHA_GPREL16:
            value -= gp;
            if ((short) value != value)
                goto reloc_overflow;
            *(u16 *)location = value;
            break;
        default:
            printk(KERN_ERR "module %s: Unknown relocation: %lu\n",
                   me->name, r_type);
            return -ENOEXEC;
        reloc_overflow:
            if (ELF64_ST_TYPE (sym->st_info) == STT_SECTION)
              printk(KERN_ERR
                     "module %s: Relocation (type %lu) overflow vs section %d\n",
                     me->name, r_type, sym->st_shndx);
            else
              printk(KERN_ERR
                     "module %s: Relocation (type %lu) overflow vs %s\n",
                     me->name, r_type, strtab + sym->st_name);
            return -ENOEXEC;
        }
    }

    return 0;
}