/** 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); } }
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; }