int elfsyms_main(int argc, char **argv) { int fd,nsyms; CexpSymTbl t; CexpSym symp; if (argc<2) { fprintf(stderr,"Need a file name\n"); return 1; } t=cexpSlurpElf(argv[1]); if (!t) { return 1; } fprintf(stderr,"%i symbols found\n",t->nentries); symp=t->syms; for (nsyms=0; nsyms<t->nentries; nsyms++) { symp=t->aindex[nsyms]; fprintf(stderr, "%02i 0x%08xx (%2i) %s\n", symp->value.type, symp->value.ptv, symp->size, symp->name); symp++; } cexpFreeSymTbl(&t); return 0; }
CexpSymTbl cexpAddSymTbl(CexpSymTbl stbl, void *syms, int symSize, int nsyms, CexpSymFilterProc filter, CexpSymAssignProc assign, void *closure, unsigned flags) { char *sp,*dst; const char *symname; CexpSymTbl rval; CexpSym cesp; int n,nDstSyms,nDstChars; CexpStrTbl strtbl = 0; if ( stbl ) { rval = stbl; } else { if (! (rval=(CexpSymTbl)calloc(1, sizeof(*rval)))) return 0; } if ( filter && assign ) { if ( rval->syms && 0 == rval->size ) { /* cannot add to a table that we didn't create */ return 0; } /* count the number of valid symbols */ if ( (flags & CEXP_SYMTBL_FLAG_NO_STRCPY) ) { for (sp=syms,n=0,nDstSyms=0; n<nsyms; sp+=symSize,n++) { if ((symname=filter(sp,closure))) { nDstSyms++; } } nDstChars = 0; } else { for (sp=syms,n=0,nDstSyms=0,nDstChars=0; n<nsyms; sp+=symSize,n++) { if ((symname=filter(sp,closure))) { nDstChars+=strlen(symname)+1; nDstSyms++; } } } /* create our copy of the symbol table - the object format contains * many things we're not interested in and also, it's not * sorted... */ if ( nDstSyms > rval->size - rval->nentries ) { /* allocate all the table space */ if ( ! (rval->syms=(CexpSym)realloc(rval->syms, sizeof(rval->syms[0])*(rval->nentries + nDstSyms + 1))) ) goto cleanup; rval->size = rval->nentries + nDstSyms; } if ( nDstChars ) { if ( !(strtbl = malloc(sizeof(*strtbl))) ) goto cleanup; if ( !(strtbl->chars = malloc(nDstChars)) ) { free( strtbl ); strtbl = 0; goto cleanup; } strtbl->next = rval->strtbl; rval->strtbl = strtbl; } /* now copy the relevant stuff */ dst = strtbl ? strtbl->chars : 0; for (sp=syms,n=0,cesp=rval->syms + rval->nentries; n<nsyms; sp+=symSize,n++) { if ((symname=filter(sp,closure))) { memset(cesp,0,sizeof(*cesp)); if ( (flags & CEXP_SYMTBL_FLAG_NO_STRCPY) ) { cesp->name=symname; } else { /* copy the name to the string table and put a pointer * into the symbol table. */ cesp->name=dst; while ((*(dst++)=*(symname++))) /* do nothing else */; } cesp->flags = 0; assign(sp,cesp,closure); cesp++; } } /* mark the last table entry */ cesp->name=0; } else { /* no filter or assign callback -- they pass us a list of symbols in already */ if ( rval->syms ) { /* cannot add an existing list of symbols to another */ return 0; } nDstSyms = nsyms; rval->syms = syms; } rval->nentries += nDstSyms; return rval; cleanup: if ( stbl ) { /* leave old table alone */ } else { cexpFreeSymTbl(&rval); } return 0; }
/* read an ELF file, extract the relevant information and * build our internal version of the symbol table. * All libelf resources are released upon return from this * routine. */ static CexpSymTbl cexpSlurpElf(char *filename) { Elf_Stream elf=0; Elf_Shdr *shdr=0; Elf_Ehdr ehdr; Pmelf_Shtab shtab = 0; Pmelf_Symtab symtab = 0; CexpSymTbl rval=0,csymt=0; CexpSym sane; #ifdef USE_ELF_MEMORY char *buf=0,*ptr=0; long size=0,avail=0,got; #ifdef __rtems__ extern struct in_addr rtems_bsdnet_bootp_server_address; char HOST[30]; #else #define HOST "localhost" #endif #endif int fd=-1; unsigned symsz; pmelf_set_errstrm(stderr); #ifdef USE_ELF_MEMORY #ifdef HAVE_RCMD if ('~'==filename[0]) { char *cmd=malloc(strlen(filename)+40); strcpy(cmd,filename); ptr=strchr(cmd,'/'); if (!ptr) { fprintf(stderr,"Illegal filename for rshLoad %s\n",filename); free(cmd); goto cleanup; } *(ptr++)=0; memmove(ptr+4,ptr,strlen(ptr)); memcpy(ptr,"cat ",4); #ifdef __rtems__ inet_ntop(AF_INET, &rtems_bsdnet_bootp_server_address, HOST, sizeof(HOST)); #endif /* try to load via rsh */ if (!(buf=rshLoad(HOST,cmd+1,ptr))) goto cleanup; } else #endif { if ((fd=open(filename,O_RDONLY,0))<0) goto cleanup; do { if (avail<LOAD_CHUNK) { size+=LOAD_CHUNK; avail+=LOAD_CHUNK; if (!(buf=realloc(buf,size))) goto cleanup; ptr=buf+(size-avail); } got=read(fd,ptr,avail); if (got<0) goto cleanup; avail-=got; ptr+=got; } while (got); got = ptr-buf; } if (!(elf = pmelf_memstrm(buf,got))) goto cleanup; #else if ( ! (elf = pmelf_newstrm(filename,0)) ) goto cleanup; #endif /* we need the section header string table */ if ( pmelf_getehdr(elf, &ehdr) || ! (shtab = pmelf_getshtab(elf, &ehdr)) || ! (symtab = pmelf_getsymtab(elf, shtab)) ) goto cleanup; /* convert the symbol table */ if ( ELFCLASS64 == ehdr.e_ident[EI_CLASS] ) { csymt=cexpCreateSymTbl( (void*)symtab->syms.p_t64, sizeof(Elf64_Sym), symtab->nsyms, filter64,assign64, (void*)symtab->strtab); } else { csymt=cexpCreateSymTbl( (void*)symtab->syms.p_t32, sizeof(Elf32_Sym), symtab->nsyms, filter32,assign32, (void*)symtab->strtab); } if ( ! csymt ) goto cleanup; #ifndef ELFSYMS_TEST_MAIN /* do a couple of sanity checks */ if ((sane=cexpSymTblLookup("cexpSlurpElf",csymt))) { extern void *_edata, *_etext; /* it must be the main symbol table */ if ( sane->value.ptv!=(CexpVal)cexpSlurpElf || !(sane=cexpSymTblLookup("_etext",csymt)) || sane->value.ptv!=(CexpVal)&_etext || !(sane=cexpSymTblLookup("_edata",csymt)) || sane->value.ptv!=(CexpVal)&_edata ) { fprintf(stderr,"ELFSYMS SANITY CHECK FAILED: you possibly loaded the wrong symbol table\n"); goto cleanup; } /* OK, sanity test passed */ } #endif rval = csymt; csymt = 0; cleanup: pmelf_delsymtab(symtab); pmelf_delshtab(shtab); pmelf_delstrm(elf,0); #ifdef USE_ELF_MEMORY if (buf) free(buf); #endif if (csymt) cexpFreeSymTbl(&csymt); if (fd>=0) close(fd); return rval; }
CexpSymTbl cexpCreateSymTbl(void *syms, int symSize, int nsyms, CexpSymFilterProc filter, CexpSymAssignProc assign, void *closure) { char *sp,*dst; const char *symname; CexpSymTbl rval; CexpSym cesp; int n,nDstSyms,nDstChars; if (!(rval=(CexpSymTbl)malloc(sizeof(*rval)))) return 0; memset(rval,0,sizeof(*rval)); if ( filter && assign ) { /* count the number of valid symbols */ for (sp=syms,n=0,nDstSyms=0,nDstChars=0; n<nsyms; sp+=symSize,n++) { if ((symname=filter(sp,closure))) { nDstChars+=strlen(symname)+1; nDstSyms++; } } /* create our copy of the symbol table - the object format contains * many things we're not interested in and also, it's not * sorted... */ /* allocate all the table space */ if (!(rval->syms=(CexpSym)malloc(sizeof(CexpSymRec)*(nDstSyms+1)))) goto cleanup; if (!(rval->strtbl=(char*)malloc(nDstChars)) || !(rval->aindex=(CexpSym*)malloc(nDstSyms*sizeof(*rval->aindex)))) goto cleanup; /* now copy the relevant stuff */ for (sp=syms,n=0,cesp=rval->syms,dst=rval->strtbl; n<nsyms; sp+=symSize,n++) { if ((symname=filter(sp,closure))) { memset(cesp,0,sizeof(*cesp)); /* copy the name to the string table and put a pointer * into the symbol table. */ cesp->name=dst; while ((*(dst++)=*(symname++))) /* do nothing else */; cesp->flags = 0; rval->aindex[cesp-rval->syms]=cesp; assign(sp,cesp,closure); cesp++; } } /* mark the last table entry */ cesp->name=0; } else { /* no filter or assign callback -- they pass us a list of symbols in already */ nDstSyms = nsyms; if ( !(rval->aindex=(CexpSym*)malloc(nDstSyms*sizeof(*rval->aindex))) ) goto cleanup; rval->syms = syms; for ( cesp = rval->syms; cesp->name; cesp++ ) { rval->aindex[cesp-rval->syms] = cesp; } } rval->nentries=nDstSyms; /* sort the tables */ qsort((void*)rval->syms, rval->nentries, sizeof(*rval->syms), _cexp_namecomp); qsort((void*)rval->aindex, rval->nentries, sizeof(*rval->aindex), _cexp_addrcomp); return rval; cleanup: cexpFreeSymTbl(&rval); return 0; }