This is rsym.c in view mode; [Download] [Up]
/* Copyright William Schelter. All rights reserved. Use this to build an executable rsym, which will grab only the external symbols from an object file, and put them in a simple format: (cf ext_sym.h) This information will be used for relocation. to compile use cc rsym.c -o rsym -I../h */ #define IN_RSYM 1 #include <stdio.h> #include "config.h" #ifdef SPECIAL_RSYM #include SPECIAL_RSYM #else /* #include "mdefs.h" */ #include "ext_sym.h" #ifdef ATT /* #include <ldfcn.h> */ #endif struct filehdr my_header; int nsyms; struct syment *symbol_table; char *my_string_table; char *start_address; #ifdef RSYM_AUX #include RSYM_AUX #endif /* our defs */ #define TABLE_SIZE 3 #ifdef DEBUG int debug =1; #undef dprintf #define dprintf(s,ar) if(debug) { printf(" ( s )",ar) ; fflush(stdout);} #else int debug =0; #define dprintf(s,ar) #endif /* this program will get the external symbols from a file writing them out to a file together with their addresses */ static char *outfile; main(argc,argv) int argc ; char *argv[]; { if (argc!=3) {perror("bad arg count"); fflush(stdout); exit(1);} #ifdef SET_BINARY_MODE SET_BINARY_MODE #endif get_myself(argv[1]); output_externals(outfile=argv[2]); exit(0); } get_myself(filename) char *filename; { unsigned int i; FILE *fp; int string_size=0; extern char *malloc(); fp = fopen(filename, RDONLY); if (fp == NULL) { fprintf(stderr, "Can't open %s\n", filename); exit(1); } HEADER_SEEK(fp); fread((char *)&my_header,sizeof(struct filehdr),1,fp); if(N_BADMAG(my_header)){ fprintf(stderr,"Bad magic %s",filename); exit(1);}; nsyms=NSYMS(my_header); symbol_table = (struct syment *)malloc(sizeof(struct syment) * nsyms); /* sizeof(struct syment) and SYMESZ are not always the same. */ if(fseek(fp,(int)(N_SYMOFF(my_header)),0)) {fprintf(stderr,"seek error"); exit(1);} for (i = 0; i < nsyms; i++) #ifdef HPUX { fread((char *)&symbol_table[i], SYMESZ, 1, fp); dprintf(string_size %d,string_size); symbol_table[i].n_un.n_strx = string_size; string_size += symbol_table[i].n_length + 1; fseek(fp,symbol_table[i].n_length,1); } #else fread((char *)&symbol_table[i], SYMESZ, 1, fp); #endif /* If the string table is not empty, its length is stored after the symbol table, This is not described in the manual, and may change in the future. */ /* fseek(fp,N_STROFF(my_header),0); strings follow symbol table! */ #ifndef HPUX #ifdef N_STROFF fseek(fp,N_STROFF(my_header),0); #endif if (fread((char *)&string_size, 4, 1, fp) > 0) { my_string_table = malloc(string_size); if(debug) {printf(" string_size is %d fseek %d ",string_size,fseek(fp,string_size-1,1)); printf(" fseek back %d ",fseek(fp,1-string_size,1));}; fseek(fp, -4, 1); if(string_size!=(fread(my_string_table, 1, string_size, fp))) {dprintf( string_size was %d ,string_size); perror("rsym could not read bad string table") ; exit(1);} } else {fprintf(stderr,"Error: There is no string table \n"); exit(1);} #else { char *p; int slen; p = my_string_table=malloc((unsigned int)string_size); dprintf( string table leng = %d, string_size); fseek(fp,(int)( LESYM_OFFSET(my_header)), 0); for (i = 0; i < nsyms; i++) { fseek(fp,SYMESZ, 1); slen = symbol_table[i].n_length; dprintf( slen = %d,slen); fread(p,slen,1,fp); *((p)+slen) = '\0'; dprintf( p = %s,p ); dprintf(symbol_table[i].n_type %d, symbol_table[i].n_type); p += symbol_table[i].n_length + 1; } } #endif fclose(fp); } struct lsymbol_table tab; output_externals(out) char *out; {FILE *symout; char *name; char tem[SYMNMLEN+1]; struct syment *p, *end; tem[SYMNMLEN]=0; tab.n_symbols=0; tab.tot_leng=0; symout=fopen(out,"wr"); if (!symout) {perror(out); exit(1);}; fseek(symout,sizeof(struct lsymbol_table),0); end = symbol_table + nsyms; for (p = symbol_table; p < end; p++) { /* Is the following check enough? */ if (EXT_and_TEXT_BSS_DAT(p)) { name= SYM_NAME(p); { dprintf(tab.n_symbols %d , tab.n_symbols); tab.n_symbols++; {int i = (p->n_value); #ifdef AIX3 if (p->n_scnum == TEXT_NSCN) i = i + 0x10000e00; else i += DBEGIN; /* leave space for the toc entry. */ #endif fwrite((char *)&i,sizeof(int),1,symout);} #ifdef AIX3 {short j=0; fwrite((char *)&j,sizeof(short),1,symout);} #endif dprintf( p->n_value %d , p->n_value); dprintf( name %s , name); while(tab.tot_leng++,*name) putc(*name++,symout); putc(0,symout); /* fprintf(symout,name); fprintf(symout," %d ", p->n_value); */ }; dprintf( NUM_AUX(p) %d , NUM_AUX(p)); dprintf( index , (int) (p - symbol_table) / sizeof(struct syment)); p = p + NUM_AUX(p); } } fseek(symout,0,0); fwrite(&tab,sizeof(tab),1,symout); fclose(symout); #ifdef AIX3 add_tc_offsets(outfile); #endif return 0; } #ifdef AIX3 int node_compare(); struct node * find_sym(sym,name) struct syment *sym; char *name; { char tem[SYMNMLEN +1]; tem [SYMNMLEN] = 0; if (name==0) name = SYM_NAME(sym); {struct node joe; joe.string=name; return (struct node *) bsearch((char *)(&joe),(char*) (c_table.ptable), c_table.length, sizeof(struct node), node_compare); }} add_tc_offsets(out) char *out; {FILE *symin; char *symbols; char *name; int i,jj; symin=fopen(out ,"r"); if(!symin) perror("can't open"); if(!fread((char *)&tab,sizeof(tab),1,symin)) perror("No header"); symbols=malloc(tab.tot_leng); c_table.alloc_length=( (PTABLE_EXTRA+ tab.n_symbols)); (c_table.ptable) = (TABL *) malloc(sizeof(struct node) * c_table.alloc_length); if (!(c_table.ptable)) {perror("could not allocate"); exit(1);}; i=0; c_table.length=tab.n_symbols; while(i < tab.n_symbols) {unsigned short tc_off; fread((char *)&jj,sizeof(int),1,symin); fread((char *)&tc_off,sizeof(short),1,symin); SYM_TC_OFF(c_table,i) = tc_off; (SYM_ADDRESS(c_table,i))=jj; SYM_STRING(c_table,i)=symbols; while( *(symbols++) = getc(symin)) {;} dprintf( "(name %s ", SYM_STRING(c_table,i)); dprintf( "addr %x )" , jj); i++; } qsort((char*)(c_table.ptable),(int)(c_table.length), sizeof(struct node),node_compare); {struct syment *sym, *end = symbol_table + nsyms; char tem[SYMNMLEN+1]; int toc_anchor =0; tem[SYMNMLEN]=0; for (sym=symbol_table ; sym < end ; sym = sym +1+ NUM_AUX(sym)) {if( sym->n_scnum != DATA_NSCN || NUM_AUX(sym) == 0) continue; if (toc_anchor == 0 && ((union auxent *)(sym+1))->x_csect.x_smclas == XMC_TC0) {toc_anchor = sym->n_value; continue;} if (((union auxent *)(sym+1))->x_csect.x_smclas == XMC_TC) { struct node joe; struct node *answ; name = SYM_NAME(sym); joe.string = name; answ = (struct node *) bsearch((char *)(&joe),(char*) (c_table.ptable), c_table.length, sizeof(struct node), node_compare); if (answ == 0) continue; if(toc_anchor ==0) {printf("TC symbol before tco"); continue;} answ->tc_offset = (sym->n_value - toc_anchor); }} /* fix ptrgl to point to the one in the data section for shorter branches */ {struct node *a=find_sym(0,"myptrgl"); if (a == 0 ) printf("couldn't find ptrgl"); else {a->string[0]= '.'; a->string[1]= '_'; a->tc_offset = 0;} } fclose(symin); symin=fopen(out,"w"); if(symin==0) perror("can't open"); fwrite(&tab,sizeof(tab),1,symin); fseek(symin,sizeof(tab),0); {int i,j; unsigned short k; for (i=0 ; i < tab.n_symbols ; i++) {k = SYM_TC_OFF(c_table,i); j= SYM_ADDRESS(c_table,i); fwrite((char *)&j,sizeof(int),1,symin); fwrite((char *)&k,sizeof(short),1,symin); name = SYM_STRING(c_table,i); while(*name) {putc(*name,symin); *name++;} putc(0,symin); }}} fclose(symin); } node_compare(node1,node2) struct node *node1, *node2; { return(strcmp(node1->string, node2->string));} #endif /*aix3 */ #endif /* SPECIAL_RSYM */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.