Elf_Scn * get_scnbyname(Elf *elf, char *name, int *num) { Elf32_Ehdr * ehdr; Elf_Scn * scn; Elf32_Shdr * shdr; Elf_Data * data; int cnt, tmp; if (!num) num = &tmp; *num = 0; if ((ehdr = elf32_getehdr(elf))==NULL) return NULL; if (((scn = elf_getscn(elf, ehdr->e_shstrndx)) == NULL) || ((data = elf_getdata(scn, NULL)) == NULL)) return NULL; for (cnt = 1, scn = NULL; (scn = elf_nextscn(elf, scn)); cnt++) { if ((shdr = elf32_getshdr(scn)) == NULL) return NULL; if (! strcmp(name, (char *)data->d_buf + shdr->sh_name)) { *num = cnt; return scn; } } return NULL; }
//--------------------------------------------------------------------- Elf_Scn* getELFSectionByName(Elf* elf, char* secName) { Elf32_Ehdr* ehdr; Elf_Scn *scn; Elf32_Shdr *shdr; // Get the ELF Header ehdr = elf32_getehdr(elf); if (NULL == ehdr){ fprintf(stderr, "getELFSectionByName: Error reading ELF header\n"); return NULL; } scn = NULL; while ((scn = elf_nextscn(elf, scn)) != NULL){ if ((shdr = elf32_getshdr(scn)) != NULL){ char* CurrSecName = NULL; CurrSecName = elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name); if (strcmp(CurrSecName, secName) == 0) return scn; } } return NULL; }
//--------------------------------------------------------------------- int getELFSymbolTableNdx(Elf* elf, char* symName) { Elf_Scn *scn; Elf32_Shdr *shdr; Elf_Data *edata; Elf32_Sym *esym; scn = NULL; while ((scn = elf_nextscn(elf, scn)) != NULL){ if ((shdr = elf32_getshdr(scn)) != NULL){ if (SHT_SYMTAB == shdr->sh_type){ edata = NULL; while ((edata = elf_getdata(scn, edata)) != NULL){ if (ELF_T_SYM == edata->d_type){ int numSymbols, i; char* symNameRead; esym = (Elf32_Sym*)(edata->d_buf); numSymbols = (int)(edata->d_size/shdr->sh_entsize); for (i = 0; i < numSymbols; i++){ symNameRead = elf_strptr(elf, shdr->sh_link, esym[i].st_name); if (strcmp(symNameRead, symName) == 0){ return i; } } } } } } } fprintf(stderr, "getElfSymbolTableNdx: Could not locate symbol in the symbol table.\n"); return -1; }
Elf32_Shdr *xelf32_getshdr(Elf_Scn *scn) { Elf32_Shdr *shdr = elf32_getshdr(scn); if (shdr == NULL) { eprintf("elf_newshdr() failed: %s", elf_errmsg(-1)); exit(EXIT_FAILURE); } return shdr; }
/* * Load template of the function described by the given symbol. */ static struct code_template* function_template_load32(Elf* e, Elf32_Sym* func32) { Elf_Scn* scn = elf_getscn(e, func32->st_shndx); assert(scn); Elf32_Shdr* shdr32 = elf32_getshdr(scn); assert(shdr32); return ct_load(e, scn, func32->st_value, func32->st_size, shdr32->sh_addralign); }
//--------------------------------------------------------------------- static int convElfHdr(Melf_Scn* mscn, Elf_Scn* escn) { Elf32_Shdr *shdr; if ((shdr = elf32_getshdr(escn)) == NULL){ fprintf(stderr, "Error reading section header.\n"); return -1; } mscn->m_shdr.sh_id = (Melf_Half)elf_ndxscn(escn); mscn->m_shdr.sh_type = shdr->sh_type; mscn->m_shdr.sh_link = shdr->sh_link; mscn->m_shdr.sh_info = shdr->sh_info; return 0; }
/* if this function encounters an error it never returns */ static void exec_getsection( Elf *elf, size_t index, Elf32_Shdr **shdr, Elf_Data **data, int line ) #define exec_getsection(a,b,c,d) \ exec_getsection(a,b,c,d,__LINE__) { Elf_Scn *section; char *location; location = NULL; section = elf_getscn( elf, index ); if ( section ) { if ( shdr ) { *shdr = elf32_getshdr(section); if ( *shdr == NULL ) { location = "elf32_getshdr"; } } if ( location == NULL && data ) { *data = elf_getdata(section, NULL); if ( *data == NULL ) { location = "elf_getdata"; } else if ( (*data)->d_buf == NULL ) { location = "d_buf"; } } if ( location == NULL ) { return; } } else { location = "elf_getscn"; } fprintf( stderr, "exec_getsection: %s@%d - %s\n", location, line, elf_errmsg( -1 ) ); exit( 1 ); }
//--------------------------------------------------------------------- static int initSymbolMap(symbol_map_t* symmap, Elf_Scn* symtabscn) { Elf32_Shdr *shdr; Elf_Data *edata; if ((shdr = elf32_getshdr(symtabscn)) == NULL){ fprintf(stderr, "Error reading symbol table section header.\n"); return -1; } if (SHT_SYMTAB != shdr->sh_type){ fprintf(stderr, "Not a symbol table section.\n"); return -1; } edata = NULL; while ((edata = elf_getdata(symtabscn, edata)) != NULL){ if (ELF_T_SYM == edata->d_type){ int i; symmap->esym = (Elf32_Sym*)edata->d_buf; //esym = (Elf32_Sym*)edata->d_buf; symmap->numE = (int)(edata->d_size/ shdr->sh_entsize); if ((symmap->msym = malloc(sizeof(Melf_Sym)* symmap->numE)) == NULL){ fprintf(stderr, "Error allocating memory.\n"); return -1; } if ((symmap->etommap = malloc(sizeof(int)* symmap->numE)) == NULL){ fprintf(stderr, "Error allocating memory.\n"); return -1; } #ifdef DBGMODE if ((symmap->mtoemap = malloc(sizeof(int)* symmap->numE)) == NULL){ fprintf(stderr, "Error allocating memory.\n"); return -1; } for (i = 0; i < symmap->numE; i++) symmap->mtoemap[i] = -1; #endif symmap->numM = 0; for (i = 0; i < symmap->numE; i++) symmap->etommap[i] = -1; return 0; } } fprintf(stderr, "Section does not contain any symbols.\n"); return -1; }
int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "%s input\n", argv[0]); return 1; } const char* elfinput = argv[1]; if (elf_version(EV_CURRENT) == EV_NONE) { fprintf(stderr, "Elf library out of date\n"); return 1; } int fd = open(elfinput, O_RDONLY); if (fd < 0) { perror(elfinput); return 1; } Elf* elf = elf_begin(fd, ELF_C_READ, NULL); Elf32_Ehdr* ehdr = elf32_getehdr(elf); Elf_Scn* section = NULL; while ((section = elf_nextscn(elf, section)) != NULL) { Elf32_Shdr* shdr; if ((shdr = elf32_getshdr(section)) != NULL) { const char* name = elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name); if (strcmp(name, ".directive")) continue; Elf_Data* data = NULL; if ((data = elf_rawdata(section, data)) == NULL || data->d_size == 0 || data->d_buf == 0) continue; fwrite(data->d_buf, 1, data->d_size, stdout); fprintf(stdout, "\n"); elf_end(elf); close(fd); return 0; } } fprintf(stderr, "No .directive section found!\n"); elf_end(elf); close(fd); return 1; }
//--------------------------------------------------------------------- char* getELFSectionName(Elf* elf, int ndx) { Elf32_Ehdr* ehdr; Elf_Scn *scn; Elf32_Shdr *shdr; if ((ehdr = elf32_getehdr(elf)) == NULL){ fprintf(stderr, "Error reading ELF header\n"); return NULL; } if ((scn = elf_getscn(elf, ndx)) == NULL){ fprintf(stderr, "Error reading ELF section table.\n"); return NULL; } if ((shdr = elf32_getshdr(scn)) == NULL){ fprintf(stderr, "Error reading ELF section header.\n"); return NULL; }; return elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name); }
void print(Elf *elf, Elf32_Ehdr *ehdr, struct list *sections, FILE *fp) { struct list *list; for(list = sections; list; list = list->next) { int section; for(section = 0; section < ehdr->e_shnum; section++) { Elf_Scn *scn; if((scn = elf_getscn(elf, section))) { Elf32_Shdr *shdr; if((shdr = elf32_getshdr(scn))) { char *p; if((p = elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name))) { if(!strcmp(p, list->string)) { Elf_Data *data; for(data = 0; (data = elf_getdata(scn, data));) { // @@@ This should be elf_rawdata() but it doesn't seem to work!! if(data->d_buf && data->d_size > 0) { int n; char *str; for(n = 0, str = data->d_buf; n < data->d_size; str++, n++) { if(*str == '\0') { *str = '\n'; } } fwrite(data->d_buf, 1, data->d_size, fp); } } break; } } } } } } }
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; }
//--------------------------------------------------------------------- static Melf_Data* convProgbitsScn(Elf_Scn* progbitsscn) { Elf32_Shdr *shdr; Elf_Data *edata; Melf_Data *mdata; if ((shdr = elf32_getshdr(progbitsscn)) == NULL){ fprintf(stderr, "Error reading progbits section header.\n"); return NULL; } if (SHT_PROGBITS != shdr->sh_type){ fprintf(stderr, "Not a progbits section.\n"); return NULL; } edata = NULL; // Get the RAW data from the ELF File for the Progbits section while ((edata = elf_rawdata(progbitsscn, edata)) != NULL){ if (ELF_T_BYTE == edata->d_type){ // Allocate memory for mdata if ((mdata = malloc(sizeof(Melf_Data))) == NULL){ fprintf(stderr, "Could not allocte memory for Mini-ELF progbits mdata structure.\n"); return NULL; } if ((mdata->d_buf = malloc(edata->d_size)) == NULL){ fprintf(stderr, "Could not allocate memory for Mini-ELF progbits data.\n"); return NULL; } mdata->d_type = ELF_T_BYTE; memcpy(mdata->d_buf, edata->d_buf, edata->d_size); mdata->d_size = edata->d_size; mdata->d_numData = edata->d_size; return mdata; } } fprintf(stderr, "No data in the progbits section.\n"); return NULL; }
static Elf_Scn* extract_elf_section (Elf *elfP, Elf_Data *secHdr, const SectionDesc* desc) { int cnt = 0; Elf_Scn* scn = NULL; Elf32_Shdr* shdr = NULL; char* sectionName = NULL; /* Iterate thru the elf sections */ for (cnt = 1, scn = NULL; scn = elf_nextscn(elfP, scn); cnt++) { if (((shdr = elf32_getshdr(scn)) == NULL)) { return NULL; } sectionName = (char *)secHdr->d_buf + shdr->sh_name; if (sectionName && ((strcmp(sectionName, desc->brigName) == 0) || (strcmp(sectionName, desc->bifName) == 0))) { return scn; } } return NULL; }
//--------------------------------------------------------------------- Elf_Scn* getELFSymbolTableScn(Elf* elf) { Elf_Scn *scn; Elf32_Shdr *shdr; Elf_Data *edata; scn = NULL; while ((scn = elf_nextscn(elf, scn)) != NULL){ if ((shdr = elf32_getshdr(scn)) != NULL){ if (SHT_SYMTAB == shdr->sh_type){ edata = NULL; while ((edata = elf_getdata(scn, edata)) != NULL){ if (ELF_T_SYM == edata->d_type){ DEBUG("No. of symbols: %d\n", (int)(edata->d_size/shdr->sh_entsize)); return scn; //return (Elf32_Sym*)(edata->d_buf); } } } } } return NULL; }
void *NWMovies_lookup_symbol(char *filename, char *function) { Elf *elf_ptr; int fd; Elf32_Ehdr *ehdr; Elf_Scn *section; Elf32_Shdr *section_header; Elf32_Sym *symtab_start, *symtab_current; int symtab_count, i; char *strtab; int strtab_type; char *symstrtab; void *return_val; /* Initialize the elves. */ if (elf_version(EV_CURRENT) == EV_NONE) { fprintf(stderr, "ERROR: NWMovies: libelf version mismatch.\n"); abort(); } /* open shared library */ fd = open(filename, O_RDONLY); if( fd < 0 ) { fprintf(stderr, "ERROR: NWMovies: Unable to open shared library: %s (%d)\n", filename, errno); abort(); } elf_ptr = elf_begin(fd, ELF_C_READ, (Elf *)0); if( elf_ptr == NULL) { fprintf(stderr, "ERROR: NWMovies: elf_begin failed: %s.\n", elf_errmsg(elf_errno())); abort(); } /* Get the Header */ if ( (ehdr = elf32_getehdr(elf_ptr)) == NULL) { fprintf(stderr, "ERROR: NWMovies: Unable to get Elf header: %s\n", elf_errmsg(elf_errno()) ); abort(); } /* Find the section string table */ section = elf_getscn(elf_ptr, ehdr->e_shstrndx); symstrtab = elf_getdata(section, NULL)->d_buf; section = 0; symtab_start = NULL; strtab = NULL; strtab_type = -1; while( (section = elf_nextscn( elf_ptr, section )) ) { section_header = elf32_getshdr(section); /* DYNSYM is better than nothing */ if( symtab_start == NULL && section_header->sh_type == SHT_DYNSYM ) { symtab_start = elf_getdata(section, NULL)->d_buf; symtab_count = section_header->sh_size / section_header->sh_entsize; strtab_type = 0; } /* However, we prefer SYMTAB */ if( section_header->sh_type == SHT_SYMTAB ) { symtab_start = elf_getdata(section, NULL)->d_buf; symtab_count = section_header->sh_size / section_header->sh_entsize; strtab_type = 1; } } if( strtab_type == -1 ) { fprintf(stderr, "ERROR: NWMovies: didn't find any symbol tables. Positively won't work.\n"); fprintf(stderr, "ERROR: NWMovies: Try a different %s library\n", filename); abort(); } section = 0; while((section = elf_nextscn(elf_ptr, section))) { section_header = elf32_getshdr(section); if( section_header->sh_type == SHT_STRTAB ) { if( strtab_type == 0 && strcmp(section_header->sh_name + symstrtab, ".dynstr") == 0 ) { strtab = elf_getdata(section, NULL)->d_buf; break; } if( strtab_type == 1 && strcmp(section_header->sh_name + symstrtab, ".strtab") == 0 ) { strtab = elf_getdata(section, NULL)->d_buf; break; } } } symtab_current = symtab_start; for(i=0; i<symtab_count; i++) { // fprintf(stderr, "DEBUG: INDEX: %d: %d\n", i, symtab_current->st_name); if( symtab_current->st_name != 0 ) { // fprintf(stderr, "DEBUG: Testing: %s\n", symtab_current->st_name + strtab); if( ! strcmp(symtab_current->st_name+strtab,function) ) { break; } } symtab_current++; } if( i >= symtab_count ) { elf_end(elf_ptr); close(fd); return(NULL); } else { return_val = (void *)symtab_current->st_value; elf_end(elf_ptr); close(fd); return(return_val); } }
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; }
int add_object_sections(NAME_LIST *section_name_list) { OBJECT_FILE **current; Elf_Scn *elf_section; Elf32_Shdr *shdr; NAME_LIST *section_name; Elf_Scn **array; int scns_available; int scns_added; array_index_t link_index; int page_links; const char *input_name; scns_added = scns_available = 0; array = NULL; array_index_init( &link_index, &link_array ); current = (OBJECT_FILE **)array_index_next_page( &link_index, &page_links ); while (current) { elf_section = NULL; while ((elf_section = elf_nextscn((*current)->elf, elf_section)) != 0) { shdr = elf32_getshdr(elf_section); elfcheck( shdr != NULL ); if ( shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS ) { input_name = (*current)->strings+shdr->sh_name; for ( section_name = section_name_list ; section_name ; section_name = section_name->next ) { if (strcmp( input_name, section_name->name) == 0) { if ((shdr->sh_flags & SHF_REFERENCED) == 0) { if ( scns_added >= scns_available ) { array_update( &scn_array, scns_added ); scns_added = 0; array = array_alloc( &scn_array, &scns_available ); } *array++ = elf_section; ++scns_added; // elf_flagshdr( elf_section, ELF_C_SET, SHF_REFERENCED ); shdr->sh_flags |= SHF_REFERENCED; } else { yyerror( "Input section is referenced twice" ); } break; } } } } ++current; if ( --page_links == 0 ) { current = (OBJECT_FILE **)array_index_next_page( &link_index, &page_links ); } } array_update( &scn_array, scns_added ); return 1; }
static void fixup_symbols( void ) { bbtree_node_t *parent; OBJECT_FILE *file; Elf_Scn *section; Elf32_Shdr *shdr; Elf32_Sym *symbol; global_t *global_sym; int i; int compare; char *sym_name; file = objects; while (file) { section = NULL; while ((section = elf_nextscn(file->elf, section)) != 0) { shdr = elf32_getshdr(section); elfcheck( shdr != NULL ); if ( (shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) && (shdr->sh_flags & SHF_REFERENCED) == 0) { yyerror( "Section %s in file %s is not referenced\n", file->strings + shdr->sh_name, file->name ); } } symbol = file->symbols + 1; for ( i = 1 ; i < file->symbol_count ; ++i ) { sym_name = elf_strptr( file->elf, file->string_index, symbol->st_name); if (symbol->st_shndx != SHN_UNDEF) { exec_getsection( file->elf, symbol->st_shndx, &shdr, NULL ); symbol->st_value += shdr->sh_addr; if (i >= file->first_global) { parent = bbtree_preinsert( &globals, sym_name, &compare ); if (!parent || compare != 0) { global_sym = (global_t *)malloc(sizeof(*global_sym)); if (global_sym) { global_sym->file = file; global_sym->name = sym_name; global_sym->symbol = symbol; bbtree_insert( &globals, parent, &global_sym->node, compare ); } else { yyerror( "Failed to allocate memory\n" ); } } else { yyerror( "Global symbol \"%s\" multiply defined\n", sym_name ); } } } else if (i < file->first_global) { yyerror( "Symbol \"%s\" is undefined but local\n", sym_name ); } ++symbol; } file = file->next_object; } }
// read symbol table from elf_file struct symtab *build_symtab(const char *elf_file) { int fd; Elf *elf; Elf32_Ehdr *ehdr; char *names; struct symtab *symtab = NULL; if ((fd = open(elf_file, O_RDONLY)) < 0) { perror("open"); return NULL; } elf = elf_begin(fd, ELF_C_READ, NULL); if (elf == NULL || elf_kind(elf) != ELF_K_ELF) { // not an elf close(fd); return NULL; } // read ELF header if ((ehdr = elf32_getehdr(elf)) != NULL) { Elf_Scn *scn; struct elf_section *scn_cache, *scn_cache_ptr; int cnt; // read section headers into scn_cache scn_cache = (struct elf_section *) malloc(ehdr->e_shnum * sizeof(struct elf_section)); scn_cache_ptr = scn_cache; scn_cache_ptr++; for (scn = NULL; scn = elf_nextscn(elf, scn); scn_cache_ptr++) { scn_cache_ptr->c_shdr = elf32_getshdr(scn); scn_cache_ptr->c_data = elf_getdata(scn, NULL); } for (cnt = 1; cnt < ehdr->e_shnum; cnt++) { Elf32_Shdr *shdr = scn_cache[cnt].c_shdr; if (shdr->sh_type == SHT_SYMTAB) { Elf32_Sym *syms; int j, n, rslt; size_t size; // FIXME: there could be multiple data buffers associated with the // same ELF section. Here we can handle only one buffer. See man page // for elf_getdata on Solaris. guarantee(symtab == NULL, "multiple symtab"); symtab = (struct symtab *)calloc(1, sizeof(struct symtab)); // the symbol table syms = (Elf32_Sym *)scn_cache[cnt].c_data->d_buf; // number of symbols n = shdr->sh_size / shdr->sh_entsize; // create hash table, we use hcreate_r, hsearch_r and hdestroy_r to // manipulate the hash table. symtab->hash_table = calloc(1, sizeof(struct hsearch_data)); rslt = hcreate_r(n, symtab->hash_table); guarantee(rslt, "unexpected failure: hcreate_r"); // shdr->sh_link points to the section that contains the actual strings // for symbol names. the st_name field in Elf32_Sym is just the // string table index. we make a copy of the string table so the // strings will not be destroyed by elf_end. size = scn_cache[shdr->sh_link].c_data->d_size; symtab->strs = (char *)malloc(size); memcpy(symtab->strs, scn_cache[shdr->sh_link].c_data->d_buf, size); // allocate memory for storing symbol offset and size; symtab->symbols = (struct elf_symbol *)malloc(n * sizeof(struct elf_symbol)); // copy symbols info our symtab and enter them info the hash table for (j = 0; j < n; j++, syms++) { ENTRY item, *ret; char *sym_name = symtab->strs + syms->st_name; symtab->symbols[j].name = sym_name; symtab->symbols[j].offset = syms->st_value; symtab->symbols[j].size = syms->st_size; // skip empty strings if (*sym_name == '\0') continue; item.key = sym_name; item.data = (void *)&(symtab->symbols[j]); hsearch_r(item, ENTER, &ret, symtab->hash_table); } } } free(scn_cache); } elf_end(elf); close(fd); return symtab; }
static int _elf_nlist(Elf *elf, struct nlist *nl) { Elf_Scn *symtab = NULL; Elf_Scn *strtab = NULL; Elf_Data *symdata; Elf_Data *strdata; Elf32_Ehdr *ehdr; Elf32_Shdr *shdr; Elf_Scn *scn; Elf32_Sym *symbols; const char *strings; unsigned nsymbols; unsigned nstrings; unsigned i; const char *name; struct hash *table; unsigned nhash; unsigned long hash; unsigned long j; long val; if (!(ehdr = elf32_getehdr(elf))) { return -1; } scn = NULL; elf_errno(); while ((scn = elf_nextscn(elf, scn))) { if (!(shdr = elf32_getshdr(scn))) { return -1; } if (shdr->sh_type != SHT_SYMTAB && shdr->sh_type != SHT_DYNSYM) { continue; } symtab = scn; strtab = elf_getscn(elf, shdr->sh_link); if (shdr->sh_type == SHT_SYMTAB) { break; } } if (elf_errno()) { return -1; } symdata = elf_getdata(symtab, NULL); strdata = elf_getdata(strtab, NULL); if (!symdata || !strdata) { return -1; } symbols = (Elf32_Sym*)symdata->d_buf; strings = (const char*)strdata->d_buf; nsymbols = symdata->d_size / sizeof(Elf32_Sym); nstrings = strdata->d_size; if (!symbols || !strings || !nsymbols || !nstrings) { return -1; } /* * build a simple hash table */ nhash = 3 * nsymbols - 4; if (!(table = (struct hash*)malloc(nhash * sizeof(*table)))) { return -1; } for (i = 0; i < nhash; i++) { table[i].name = NULL; table[i].sym = NULL; } for (i = 1; i < nsymbols; i++) { if (symbols[i].st_name < 0 || symbols[i].st_name >= nstrings) { free(table); return -1; } if (symbols[i].st_name == 0) { continue; } name = strings + symbols[i].st_name; hash = elf_hash(name); for (j = hash; table[j %= nhash].name; j += 3) { if (table[j].hash != hash) { continue; } if (table[j].name == name || !strcmp(table[j].name, name)) { break; } } table[j].hash = hash; table[j].name = name; table[j].sym = &symbols[i]; } /* * symbol lookup */ for (i = 0; (name = nl[i].n_name) && *name ; i++) { val = nl[i].n_value; if (!strcmp("__UNKNOWN__", name)) { for (j=0; j < nhash; j++) if ((table[j].sym != NULL) && (table[j].sym->st_value == val)) { break; } if (j != nhash) { if ((nl[i].n_name = malloc(strlen(table[j].name)+1)) == NULL) return -1; strcpy(nl[i].n_name,table[j].name); nl[i].n_scnum = table[j].sym->st_shndx; } else { nl[i].n_name = NULL; nl[i].n_scnum = 0; } } else { hash = elf_hash(name); for (j = hash; table[j %= nhash].name; j += 3) { if ( (table[j].hash == hash) && (!strcmp(table[j].name, name)) ) { break; } } if (table[j].name) { nl[i].n_value = table[j].sym->st_value; nl[i].n_scnum = table[j].sym->st_shndx; } else { nl[i].n_value = 0; nl[i].n_scnum = 0; } } /* * this needs more work */ nl[i].n_type = 0; nl[i].n_sclass = 0; nl[i].n_numaux = 0; } free(table); return 0; }
static void print_relocinfo_32 (Dwarf_Debug dbg, Elf *elf) { Elf_Scn *scn = NULL; Elf_Data *data; Elf32_Ehdr *ehdr32; Elf32_Shdr *shdr32; char *scn_name; int i; if ((ehdr32 = elf32_getehdr(elf)) == NULL) { print_error(dbg, "DW_ELF_GETEHDR_ERROR",DW_DLV_OK, err); } while ((scn = elf_nextscn(elf, scn)) != NULL) { if ((shdr32 = elf32_getshdr(scn)) == NULL) { print_error(dbg, "DW_ELF_GETSHDR_ERROR",DW_DLV_OK, err); } if ((scn_name = elf_strptr(elf,ehdr32->e_shstrndx, shdr32->sh_name) ) == NULL) { print_error(dbg, "DW_ELF_STRPTR_ERROR",DW_DLV_OK, err); } if (shdr32->sh_type == SHT_SYMTAB) { size_t sym_size = 0; size_t count = 0; if ((sym = (Elf32_Sym *) get_scndata(scn, &sym_size)) == NULL) { print_error(dbg, "no symbol table data",DW_DLV_OK, err); } sym = (Elf32_Sym *) get_scndata(scn, &sym_size); count = sym_size / sizeof (Elf32_Sym); sym ++; if ((sym_data = readsyms(sym, count, elf, shdr32->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_32(i, sect_data[i].buf, sect_data[i].size); } } }
/* 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); }
bool saveSharedLibrary::readNewLib(){ Elf32_Shdr *newsh, *shdr; Elf_Scn *scn, *newScn; Elf32_Ehdr *ehdr; Elf32_Phdr *oldPhdr; Elf_Data *strdata, *newdata, *olddata; if ((ehdr = elf32_getehdr(newElf)) == NULL){ fprintf(stderr," FAILED obtaining ehdr readNewLib\n"); return false; } if((scn = elf_getscn(newElf, ehdr->e_shstrndx)) != NULL){ if((strdata = elf_getdata(scn, NULL)) == NULL){ fprintf(stderr," Failed obtaining .shstrtab data buffer \n"); return false; } }else{ fprintf(stderr," FAILED obtaining .shstrtab scn\n"); } unsigned int newScnName =0; scn = NULL; Elf_Data shstrtabData; #if defined(i386_unknown_linux2_0) \ || defined(x86_64_unknown_linux2_4) /* save the PHDR from the library */ oldPhdr = elf32_getphdr(newElf); Elf32_Phdr phdrBuffer[ehdr->e_phnum]; /* copy it over to a buffer because, on linux, we will close newElf and reopen it. This closing of newElf should dealloc the data pointed to by oldPhdr */ memcpy(phdrBuffer, oldPhdr, ehdr->e_phnum * ehdr->e_phentsize); #endif for (int cnt = 1; (scn = elf_nextscn(newElf, scn)); cnt++) { //copy sections from newElf to newElf. shdr = elf32_getshdr(scn); olddata = elf_getdata(scn,NULL); if(!strcmp( (char *)strdata->d_buf + shdr->sh_name, ".text")){ textAddr = shdr->sh_addr; textData = olddata; textSize = shdr->sh_size; } if(!strcmp( (char*) strdata->d_buf + shdr->sh_name, ".shstrtab")){ const char *secname =".dyninst_mutated\0"; shstrtabData.d_size = olddata->d_size+strlen(secname)+1; newShstrtabData_d_buf = new char[shstrtabData.d_size]; shstrtabData.d_buf = newShstrtabData_d_buf; memcpy( shstrtabData.d_buf, olddata->d_buf, olddata->d_size); memcpy(&(((char*) shstrtabData.d_buf)[olddata->d_size]), secname, strlen(secname)+1); newScnName = olddata->d_size; olddata->d_buf = shstrtabData.d_buf; olddata->d_size = shstrtabData.d_size; shdr->sh_size +=strlen(secname)+1; /* if the section header table is past this section in the ELF file, calculate the new offset*/ if(ehdr ->e_shoff > shdr->sh_offset){ ehdr->e_shoff += strlen(secname)+1; } elf_flagscn(scn,ELF_C_SET,ELF_F_DIRTY); } } ehdr-> e_shnum++; newScn = elf_newscn(newElf); newsh = elf32_getshdr(newScn); newsh->sh_name = newScnName; newsh->sh_type = SHT_NOBITS; // SHT_NOTE; newsh->sh_flags=0; newsh->sh_addr = 0x0; newsh->sh_offset = shdr->sh_offset; newsh->sh_size=0; newsh->sh_link=0; newsh->sh_info=0; newsh->sh_addralign = 0x1; //Values 0 and 1 mean the section has no alignment constraints. newsh->sh_entsize = 0; newdata = elf_newdata(newScn); newdata->d_size =0; newdata->d_buf=0; elf_update(newElf, ELF_C_NULL); /* elfutils on linux does not write data back to an ELF file you have opened correctly. Specifically, if you add a section the section's section header has space allocated for it in the file but no data is written to it. lovely, eh? to combat this, we reopen the file we just closed, and find the empty section header and fill it with data. */ #if defined(i386_unknown_linux2_0) \ || defined(x86_64_unknown_linux2_4) elf_update(newElf, ELF_C_WRITE); elf_end(newElf); P_close(newfd); if((newfd = (open(newpathname, O_RDWR)))==-1){ fprintf(stderr,"%s[%d]: cannot open new SO : %s\n",FILE__, __LINE__, newpathname); perror(" FAIL "); return false;; } if((newElf = elf_begin(newfd, ELF_C_RDWR, NULL)) ==NULL){ fprintf(stderr,"cannot open ELF %s \n", newpathname); return false;; } if ((ehdr = elf32_getehdr(newElf)) == NULL){ fprintf(stderr," FAILED obtaining ehdr readNewLib\n"); return false; } if((scn = elf_getscn(newElf, ehdr->e_shstrndx)) != NULL){ if((strdata = elf_getdata(scn, NULL)) == NULL){ fprintf(stderr," Failed obtaining .shstrtab data buffer \n"); return false; } }else{ fprintf(stderr," FAILED obtaining .shstrtab scn\n"); } scn = NULL; bool foundText=false; for (int cnt = 1; (scn = elf_nextscn(newElf, scn)); cnt++) { //copy sections from newElf to newElf. shdr = elf32_getshdr(scn); olddata = elf_getdata(scn,NULL); if(!foundText && !strcmp( (char *)strdata->d_buf + shdr->sh_name, ".text")){ textAddr = shdr->sh_addr; textData = olddata; textSize = shdr->sh_size; elf_flagscn(scn,ELF_C_SET,ELF_F_DIRTY); foundText = true; } } /**UPDATE THE LAST SHDR **/ memset(shdr,'\0', sizeof(Elf32_Shdr)); shdr->sh_name = newScnName; shdr->sh_addr = 0x0; shdr->sh_type = 7; /* update the PHDR, well just make sure it is reset to what was in the original library */ Elf32_Phdr *newPhdr = elf32_getphdr(newElf); memcpy(newPhdr,phdrBuffer, ehdr->e_phnum * ehdr->e_phentsize); /* be extra sure, set the DIRTY flag */ elf_flagphdr(newElf, ELF_C_SET,ELF_F_DIRTY); elf_flagscn(scn,ELF_C_SET,ELF_F_DIRTY); elf_update(newElf, ELF_C_NULL); #endif return true; }
void leaky::readSymbols(const char *fileName) { int fd = ::open(fileName, O_RDONLY); if (fd < 0) { fprintf(stderr, "%s: unable to open \"%s\"\n", applicationName, fileName); exit(-1); } elf_version(EV_CURRENT); Elf *elf = elf_begin(fd, ELF_C_READ, 0); if (!elf) { fprintf(stderr, "%s: \"%s\": has no symbol table\n", applicationName, fileName); exit(-1); } long alloced = 10000; Symbol* syms = (Symbol*) malloc(sizeof(Symbol) * 10000); Symbol* sp = syms; Symbol* last = syms + alloced; // Get each of the relevant sections and add them to the list of // symbols. Elf32_Ehdr *ehdr = elf32_getehdr(elf); if (!ehdr) { fprintf(stderr, "%s: elf library lossage\n", applicationName); exit(-1); } #if 0 Elf32_Half ndx = ehdr->e_shstrndx; #endif Elf_Scn *scn = 0; int strtabndx = -1; for (int i = 1; (scn = elf_nextscn(elf, scn)) != 0; i++) { Elf32_Shdr *shdr = elf32_getshdr(scn); #if 0 char *name = elf_strptr(elf, ndx, (size_t) shdr->sh_name); printf("Section %s (%d 0x%x)\n", name ? name : "(null)", shdr->sh_type, shdr->sh_type); #endif if (shdr->sh_type == SHT_STRTAB) { /* We assume here that string tables preceed symbol tables... */ strtabndx = i; continue; } #if 0 if (shdr->sh_type == SHT_DYNAMIC) { /* Dynamic */ Elf_Data *data = elf_getdata(scn, 0); if (!data || !data->d_size) { printf("No data..."); continue; } Elf32_Dyn *dyn = (Elf32_Dyn*) data->d_buf; Elf32_Dyn *lastdyn = (Elf32_Dyn*) ((char*) data->d_buf + data->d_size); for (; dyn < lastdyn; dyn++) { printf("tag=%d value=0x%x\n", dyn->d_tag, dyn->d_un.d_val); } } else #endif if ((shdr->sh_type == SHT_SYMTAB) || (shdr->sh_type == SHT_DYNSYM)) { /* Symbol table */ Elf_Data *data = elf_getdata(scn, 0); if (!data || !data->d_size) { printf("No data..."); continue; } /* In theory we now have the symbols... */ Elf32_Sym *esym = (Elf32_Sym*) data->d_buf; Elf32_Sym *lastsym = (Elf32_Sym*) ((char*) data->d_buf + data->d_size); for (; esym < lastsym; esym++) { #if 0 char *nm = elf_strptr(elf, strtabndx, (size_t)esym->st_name); printf("%20s 0x%08x %02x %02x\n", nm, esym->st_value, ELF32_ST_BIND(esym->st_info), ELF32_ST_TYPE(esym->st_info)); #endif if ((esym->st_value == 0) || (ELF32_ST_BIND(esym->st_info) == STB_WEAK) || (ELF32_ST_BIND(esym->st_info) == STB_NUM) || (ELF32_ST_TYPE(esym->st_info) != STT_FUNC)) { continue; } #if 1 char *nm = elf_strptr(elf, strtabndx, (size_t)esym->st_name); #endif sp->name = nm ? strdup(nm) : "(no name)"; sp->address = esym->st_value; sp++; if (sp >= last) { long n = alloced + 10000; syms = (Symbol*) realloc(syms, (size_t) (sizeof(Symbol) * n)); last = syms + n; sp = syms + alloced; alloced = n; } } } } int interesting = sp - syms; if (!quiet) { printf("Total of %d symbols\n", interesting); } usefulSymbols = interesting; externalSymbols = syms; }
/* Given Elf header, Elf_Scn, and Elf32_Shdr * print out the symbol table */ void *GetSymbolAdress(const char *filename, const char *symbol) { #ifdef PLATFORM_POSIX int fd; Elf *elf; GElf_Ehdr elfhdr; if (elf_version(EV_CURRENT) == EV_NONE) { META_CONPRINTF("ELF library is out of date, Quitting\n"); } fd = open(filename, O_RDONLY); if (fd < 0) { META_CONPRINTF("[Masterhook] Unable to open \"%s\"\n", filename); } elf = elf_begin(fd, ELF_C_READ, NULL); if (gelf_getehdr(elf, &elfhdr) == 0) { META_CONPRINTF("Cannot read elf header. This usually means that %s is not a valid elf file\n", filename); } Elf_Scn* section = 0; Elf32_Shdr *shdr = NULL; bool symtabFound = false; while ((section = elf_nextscn(elf, section)) != 0) { if ((shdr = elf32_getshdr (section)) != 0) { if (shdr->sh_type == SHT_SYMTAB) { symtabFound = true; break; } } } if (shdr == NULL || !symtabFound) { return NULL; } Elf_Scn *scn = section; Elf_Data *data; char *name; data = 0; int number = 0; if ((data = elf_getdata(scn, data)) == 0 || data->d_size == 0){ META_CONPRINTF("Section had no data!\n"); return NULL; } Elf32_Sym *esym = (Elf32_Sym*) data->d_buf; Elf32_Sym *lastsym = (Elf32_Sym*) ((char*) data->d_buf + data->d_size); for (; esym < lastsym; esym++) { if ((esym->st_value == 0) || (ELF32_ST_BIND(esym->st_info) == STB_WEAK) || (ELF32_ST_BIND(esym->st_info) == STB_NUM) || (ELF32_ST_TYPE(esym->st_info) != STT_FUNC)) { continue; } name = elf_strptr(elf, shdr->sh_link , (size_t)esym->st_name); if(!name){ META_CONPRINTF("%s\n", elf_errmsg(elf_errno())); return NULL; } char *name_demangled = 0; int* status; name_demangled = abi::__cxa_demangle(name, 0, 0, status); #ifdef DEBUG META_CONPRINTF("%d: Name: %s == %s Address: 0x%x\n", number++, name_demangled, symbol, esym->st_value); #endif if (name_demangled != NULL) { if (strstr(name_demangled, symbol)) { return (void*)esym->st_value; } } //free(name_demangled); } #endif return NULL; }
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; } }
int main( int argc, char **argv ) { int fd; Elf_Scn *section; int scndx; Elf32_Shdr *sheader; Elf32_Ehdr *eheader; int strings; int len; int what_to_do; Elf *elf; char *filep; if( argc != 3 ) { fprintf(stderr, "%s: <what> <filename>\n", argv[0]); return(1); } if (strcmp("vindex",argv[1]) == 0) what_to_do = 1; else if (strcmp("type",argv[1]) == 0) what_to_do = 2; else if (strcmp("vtable",argv[1]) == 0) what_to_do = 3; else { fprintf(stderr, "%s: unknown command> %s\n", argv[0], argv[1] ); return(1); } sprintf(program,"%s<%s>",argv[0],argv[1]); elf_version(EV_CURRENT); fd = open(argv[2], OPEN_FLAGS); if( fd < 0 ) { fprintf(stderr, "%s: open of file %s failed\n", argv[0], argv[2] ); return(1); } len = lseek(fd, 0, SEEK_END); #if MAPFILE /* printf("Mapping file %s [len %d]\n", argv[1], len); */ filep = (char *) mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED,fd,0); if (filep == (char *)-1) { perror("mmap"); return(1); } #else filep = (char*)malloc(len); lseek(fd,0,SEEK_SET); if (len != read(fd,filep,len)) { perror("mmap"); return(1); } #endif elf = elf_begin(fd, ELF_C_READ, (Elf *)NULL); if ((eheader = elf32_getehdr(elf)) == NULL) { fprintf(stderr, "%s: get header failed\n", argv[0] ); return(1); } strings = eheader->e_shstrndx; section = NULL; scndx = 0; while ((section = elf_nextscn(elf, section)) != NULL) { char *name = 0; ++scndx; if ((sheader = elf32_getshdr(section)) != NULL) name = elf_strptr(elf, strings, sheader->sh_name); if( name != NULL ) { // printf("SECTION[%d]: <%s>\n",(int)section,name); if( strcmp( name, THE_DATA_SECTION ) == 0 ) { pdata = (char *) (filep + sheader->sh_offset); data_index = scndx; } else if( strcmp( name, SMALL_DATA_SECTION ) == 0 ) { psdata = (char *) (filep + sheader->sh_offset); sdata_index = scndx; } else if( strcmp( name, ELF_SYMTAB ) == 0 ) { psyms = (Elf32_Sym *) (filep + sheader->sh_offset); nsyms = sheader->sh_size / sizeof(Elf32_Sym); } else if( strcmp( name, ELF_STRTAB ) == 0 ) { pstr = (char *) (filep + sheader->sh_offset); } } } if( pdata == NULL && psdata == NULL ) { fprintf(stderr, "%s: no data segment found\n", argv[0] ); return(1); } if( psyms == NULL ) { fprintf(stderr, "%s: no symbol table found\n", argv[0] ); return(1); } if( pstr == NULL ) { fprintf(stderr, "%s: no string table found\n", argv[0] ); return(1); } switch (what_to_do) { case 1: extract_virtual_index(); break; case 2: extract_type_values(); break; case 3: extract_virtual_table_size_indirect(); break; } elf_end(elf); return(0); }
//--------------------------------------------------------------------- static Melf_Data* convRelaScn(Elf_Scn* relascn, symbol_map_t* symmap) { Elf32_Shdr *shdr; Elf_Data *edata; Elf32_Rela *erela; Melf_Rela *mrela; int numRecs, i; Melf_Data* mreladata; // Get the ELF Rela Section Header if ((shdr = elf32_getshdr(relascn)) == NULL){ fprintf(stderr, "Error reading rela section header.\n"); return NULL; } // Verify the ELF RELA section type if (SHT_RELA != shdr->sh_type){ fprintf(stderr, "Not a relocation section. \n"); return NULL; } // Get the ELF rela table edata = NULL; while ((edata = elf_getdata(relascn, edata)) != NULL){ if (ELF_T_RELA == edata->d_type){ erela = (Elf32_Rela*)edata->d_buf; numRecs = edata->d_size/shdr->sh_entsize; // Allocating memory for MELF rela table if ((mreladata = malloc(sizeof(Melf_Data))) == NULL){ fprintf(stderr, "Error allocating memory."); return NULL; } if ((mreladata->d_buf = malloc(sizeof(Melf_Rela) * numRecs)) == NULL){ fprintf(stderr, "Error allocating memory."); return NULL; } // Init the MELF rela table mreladata->d_numData = 0; mreladata->d_type = ELF_T_RELA; mrela = (Melf_Rela*)mreladata->d_buf; for (i = 0; i < numRecs; i++){ int esymndx; int msymndx; esymndx = ELF32_R_SYM(erela[i].r_info); /* // // Check whether we can patch the symbol right now // (i.e. known sys-calls) // if( patchSymbol( symmap, erela + i ) != 0 ) { continue; } */ // Get MELF Symbol Index if ((msymndx = addMelfSymbol(symmap, esymndx)) == -1){ fprintf(stderr, "Invalid symbol index in rela.\n"); return NULL; } // Convert ELF Rela record to MELF Rela record mrela[mreladata->d_numData].r_offset = (Melf_Addr)erela[i].r_offset; mrela[mreladata->d_numData].r_symbol = msymndx; mrela[mreladata->d_numData].r_type = (unsigned char)ELF32_R_TYPE(erela[i].r_info); mrela[mreladata->d_numData].r_addend = (Melf_Sword) erela[i].r_addend; // mreladata->d_numData++; } mreladata->d_size = mreladata->d_numData * sizeof(Melf_Rela); return mreladata; } } fprintf(stderr, "Section does not contain any rela records.\n"); return NULL; }
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; }