Example #1
0
/** Update this section table entry with newer information from the section */
void
SgAsmElfSectionTableEntry::update_from_section(SgAsmElfSection *section)
{
    if (section->get_name()->get_offset()==SgAsmGenericString::unallocated) {
        p_sh_name = 0; /*not a stored string after all*/
    } else {
        p_sh_name = section->get_name()->get_offset();
    }

    set_sh_offset(section->get_offset());
    if (get_sh_type()==SHT_NOBITS && section->is_mapped()) {
        set_sh_size(section->get_mapped_size());
    } else {
        set_sh_size(section->get_size());
    }

    if (section->is_mapped()) {
        set_sh_addr(section->get_mapped_preferred_rva());
        set_sh_addralign(section->get_mapped_alignment());
        if (section->get_mapped_wperm()) {
            p_sh_flags |= SHF_WRITE;
        } else {
            p_sh_flags &= ~SHF_WRITE;
        }
        if (section->get_mapped_xperm()) {
            p_sh_flags |=  SHF_EXECINSTR;
        } else {
            p_sh_flags &= ~SHF_EXECINSTR;
        }
    } else {
        set_sh_addr(0);
        p_sh_flags &= ~(SHF_WRITE | SHF_EXECINSTR); /*clear write & execute bits*/
    }
    
    SgAsmElfSection *linked_to = section->get_linked_section();
    if (linked_to) {
        ROSE_ASSERT(linked_to->get_id()>0);
        set_sh_link(linked_to->get_id());
    } else {
        set_sh_link(0);
    }
}
Example #2
0
static Pmelf_Long
_pmelf_find_symhdrs(Elf_Stream s, Pmelf_Shtab shtab, Elf_Shdr **psymsh, Elf_Shdr **pstrsh, int dynamic)
{
Elf_Shdr   *shdr;
uint32_t   i;
Elf_Shdr   *symsh  = 0;
Elf_Shdr   *strsh  = 0;
const char *name;
uint8_t    *p;
uint32_t   shdrsz = get_shdrsz(shtab);
uint32_t   symsz;
Pmelf_Size sh_size, sh_entsize;
Pmelf_Off  sh_offset;
uint32_t   type, destype;
const char *desname;
#ifndef USE_SYM_SH_LINK
const char *desstrn;
#endif

	if ( dynamic ) {
		destype = SHT_DYNSYM;
		desname = ".dynsym";
#ifndef USE_SYM_SH_LINK
		desstrn = ".dynstr";
#endif
	} else {
		destype = SHT_SYMTAB;
		desname = ".symtab";
#ifndef USE_SYM_SH_LINK
		desstrn = ".strtab";
#endif
	}
	destype = dynamic ? SHT_DYNSYM : SHT_SYMTAB;

	for ( i = 0, p = shtab->shdrs.p_raw; i<shtab->nshdrs; i++, p+=shdrsz ) {
		shdr = (Elf_Shdr*)p;

		type = get_sh_type(shtab->clss, shdr);

		if ( type == destype ) {
			if ( ! (name = pmelf_sec_name(shtab, shdr)) ) {
				PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_find_symhdrs: symtab section name out of bounds\n");
				return -1;
			}
			if ( !strcmp(desname, name) ) {
				if ( symsh ) {
					PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_find_symhdrs: multiple symtabs\n");
					return -1;
				}
				symsh = shdr;
#ifdef USE_SYM_SH_LINK
				strsh = get_shtabN(shtab,get_sh_link(shtab->clss, symsh));
#endif
			}
		}
#ifndef USE_SYM_SH_LINK
		else if ( SHT_STRTAB == type ) {
				if ( ! (name = pmelf_sec_name(shtab, shdr)) ) {
					PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_find_symhdrs: strtab section name out of bounds\n");
					return -1;
				}
				if ( !strcmp(desstrn, name) ) {
					if ( strsh ) {
						PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_find_symhdrs: multiple strtabs\n");
						return -1;
					}
					strsh = shdr;
				}
		}
#endif
	}

	if ( !symsh ) {
#if 0
		/* let the caller barf it they think it is appropriate */
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_find_symhdrs: no symtab found\n");
#endif
		return -1;
	}

#ifdef PMELF_CONFIG_ELF64SUPPORT
	if ( ELFCLASS64 == shtab->clss ) {
		sh_size    = symsh->s64.sh_size;
		sh_entsize = symsh->s64.sh_entsize;
		sh_offset  = symsh->s64.sh_offset;
		symsz      = sizeof(Elf64_Sym);
	}
	else
#endif
	{
		sh_size    = symsh->s32.sh_size;
		sh_entsize = symsh->s32.sh_entsize;
		sh_offset  = symsh->s32.sh_offset;
		symsz      = sizeof(Elf32_Sym);
	}


	if ( !strsh ) {
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_find_symhdrs: no strtab found\n");
		return -1;
	}

	if ( 0 == sh_size ) {
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_find_symhdrs: zero size symtab\n");
		return -1;
	}

	if ( sh_entsize && sh_entsize != symsz ) {
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_find_symhdrs: symbol size mismatch (sh_entsize %lu\n", (unsigned long)sh_entsize);
		return -1;
	}

	if ( (sh_size % symsz) != 0 ) {
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_find_symhdrs: sh_size of symtab not a multiple of sizeof(Elf32_Sym)\n");
		return -1;
	}

	if ( pmelf_seek(s, sh_offset) ) {
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_find_symhdrs unable to seek to symtab %s\n", strerror(errno));
		return -1;
	}

	if ( psymsh )
		*psymsh = symsh;
	if ( pstrsh )
		*pstrsh = strsh;

	return sh_size/symsz;
}