home *** CD-ROM | disk | FTP | other *** search
-
- /*
- Copyright William Schelter. All rights reserved.
- There is a companion file rsym.c which is used to build
- a list of the external symbols in a COFF or A.OUT object file, for
- example saved_kcl. These are loaded into kcl, and the
- linking is done directly inside kcl. This saves a good
- deal of time. For example a tiny file foo.o with one definition
- can be loaded in .04 seconds. This is much faster than
- previously possible in kcl.
- The function fasload from unixfasl.c is replaced by the fasload
- in this file.
- this file is included in unixfasl.c
- via #include "../c/sfasl.c"
- */
- #include <varargs.h>
-
-
- /* for testing in standalone manner define STAND
- You may then compile this file cc -g -DSTAND -DDEBUG -I../hn
- a.out /tmp/foo.o /public/akcl/unixport/saved_kcl /public/akcl/unixport/
- will write a /tmp/sfasltest file
- which you can use comp to compare with one produced by ld.
- */
-
-
- #ifdef STAND
- #include "config.h"
- #include <stdio.h>
- #include "mdefs.h"
-
- #else
- #include "include.h"
- #undef S_DATA
- #endif
-
- #include "ext_sym.h"
-
- int node_compare();
- char *malloc();
- char *the_start;
- char *bsearch();
-
- struct reloc relocation_info;
- /* next 5 static after debug */
-
- int debug;
-
- #ifdef DEBUG
- #define dprintf(s,ar) if(debug) { printf(" ( s )",ar) ; fflush(stdout);}
- #define STAT
-
- #else /* end debug */
- #define dprintf(s,ar)
- #define STAT static
- #endif
-
-
- #define MAXPATHLEN 200
- #define PTABLE_EXTRA 20
-
- STAT struct syment *symbol_table;
- STAT char *start_address;
- STAT char *my_string_table;
- STAT int extra_bss;
-
- STAT char command[200];
- STAT char tmpfile1 [50];
-
- #ifndef describe_sym
- #define describe_sym(a)
- #endif
-
- #ifdef STAND
- #include "rel_stand.c"
- #endif
-
-
- #define TEMPSPACE 50000
- char tempspace[TEMPSPACE];
- char *bil;
- char
- *temp_malloc(n)
- unsigned int n;
- {char *val;
- val=(char *) (4*((((int)bil)+4)/4));
- bil=val+n;
- if (bil < tempspace +TEMPSPACE)
- return val;
- else {bil=val;
- dprintf( having to use regular malloc for %d,n);
- return malloc(n);}
- }
-
- #include RELOC_FILE
-
- /* free up space which is not allocated in tempspace */
-
- #define TEMP_FREE(x) \
- if (((char *)x)> tempspace+TEMPSPACE || ((char *)x)< tempspace) \
- free(x)
-
- int
- fasload(faslfile)
- object faslfile;
- { long fasl_vector_start;
- struct filehdr fileheader;
- #ifdef COFF
- struct scnhdr sectionheader;
- struct scnhdr section[4];
- #endif
- int textsize, datasize, bsssize,nsyms;
- int string_size=0;
-
- object memory, data;
- FILE *fp;
- char filename[MAXPATHLEN];
- int i;
- int init_address=0;
- #ifndef STAND
- object *old_vs_base = vs_base;
- object *old_vs_top = vs_top;
- #endif
- bil=tempspace; /* reset tmp malloc */
- extra_bss=0;
- #ifdef STAND
- strcpy(filename,faslfile);
- fp=fopen(filename,RDONLY);
- #else
- coerce_to_filename(faslfile, filename);
- faslfile = open_stream(faslfile, smm_input, Cnil, Kerror);
- vs_push(faslfile);
- fp = faslfile->sm.sm_fp;
- #endif
-
- HEADER_SEEK(fp);
- if(!fread((char *)&fileheader, sizeof(struct filehdr), 1, fp))
- FEerror("Could not get the header",0,0);
- nsyms = NSYMS(fileheader);
- #ifdef COFF
- fseek(fp,fileheader.f_opthdr,1);
- fread(§ion[1], sizeof(sectionheader), 1, fp);
- textsize = section[1].s_size;
- fread((char *)§ion[2], sizeof(sectionheader), 1, fp);
- datasize = section[2].s_size;
- fread(§ionheader, sizeof(sectionheader), 1, fp);
- if (strcmp(section[3].s_name, ".bss") == 0)
- bsssize=section[3].s_size;
- else bsssize=section[3].s_size = 0;
- #endif
-
- #ifdef BSD
- textsize=fileheader.a_text;
- datasize=fileheader.a_data;
- bsssize=fileheader.a_bss;
- #endif
- symbol_table =
- (struct syment *) temp_malloc(sizeof(struct syment)*
- (unsigned int)nsyms);
- fseek(fp,(int)( N_SYMOFF(fileheader)), 0);
- {
- for (i = 0; i < nsyms; i++)
- {fread((char *)&symbol_table[i], SYMESZ, 1, fp);
- dprintf( symbol table %d , i);
- if (debug) describe_sym(i);
- dprintf( at %d , &symbol_table[i]);
- #ifdef HPUX
- symbol_table[i].n_un.n_strx = string_size;
- dprintf(string_size %d, string_size);
- string_size += symbol_table[i].n_length + 1;
- fseek(fp,(int)symbol_table[i].n_length,1);
- #endif
- }
- }
- /*
- on MP386
- The sizeof(struct syment) = 20, while only SYMESZ =18. So we had to read
- one at a time.
- fread((char *)symbol_table, SYMESZ*fileheader.f_nsyms,1,fp);
- */
-
- #ifdef READ_IN_STRING_TABLE
-
- my_string_table=READ_IN_STRING_TABLE(fp,string_size);
-
- #else
- #ifdef MUST_SEEK_TO_STROFF
- fseek(fp,N_STROFF(fileheader),0);
- #endif
- {int ii=0;
- if (!fread((char *)&ii,sizeof(int),1,fp))
- {FEerror("The string table of this file did not have any length",0,
- 0);}
- fseek(fp,-4,1);
- /* at present the string table is located just after the symbols */
- my_string_table=temp_malloc((unsigned int)ii);
- dprintf( string table leng = %d, ii);
-
- if(ii!=fread(my_string_table,1,ii,fp))
- FEerror("Could not read whole string table",0,0) ;
- }
- #endif
- #ifdef SEEK_TO_END_OFILE
- SEEK_TO_END_OFILE(fp);
- #else
- while ((i = getc(fp)) == 0)
- ;
- ungetc(i, fp);
- #endif
-
- fasl_vector_start=ftell(fp);
-
- if (!((c_table.ptable) && *(c_table.ptable)))
- build_symbol_table();
-
- /* figure out if there is more bss space needed */
- extra_bss=get_extra_bss(symbol_table,nsyms,datasize+textsize+bsssize,
- &init_address);
-
- /* allocate some memory */
- #ifndef STAND
- memory = alloc_object(t_cfdata);
- memory->cfd.cfd_self = 0;
- memory->cfd.cfd_start = 0;
- memory->cfd.cfd_size = datasize+textsize+bsssize + extra_bss;
- vs_push(memory);
- the_start=start_address=
- memory->cfd.cfd_start =
- alloc_contblock(memory->cfd.cfd_size);
-
- #else
- the_start=start_address
- = malloc(datasize+textsize+bsssize + extra_bss + 0x80000);
- the_start=start_address= (char *)(
- 0x1000* ((((int)the_start + 0x70000) + 0x1000)/0x1000));
-
- #endif
- dprintf( code size %d , datasize+textsize+bsssize + extra_bss);
- if (fseek(fp,N_TXTOFF(fileheader) ,0) < 0)
- FEerror("file seek error",0,0);
- fread(the_start, textsize + datasize, 1, fp);
- dprintf(read into memory text +data %d bytes, textsize + datasize);
- /* relocate the actual loaded text */
-
- dprintf( the_start %x, the_start);
-
- /* this looks up symbols in c.ptable and also adds new externals to
- that c.table */
- relocate_symbols(NSYMS(fileheader));
-
- #ifdef COFF
- {int j=0;
- for(j=1; j<3 ; j++)
- { dprintf( relocating section %d \n,j);
- fseek(fp,section[j].s_relptr,0);
- for(i=0; i < section[j].s_nreloc; i++)
- {fread(&relocation_info, 10, 1, fp);
- dprintf(relocating %d,i);
- relocate();};
- }};
- #endif
- #ifdef BSD
- fseek(fp,N_RELOFF(fileheader),0);
- {int nrel = (fileheader.a_trsize/sizeof(struct reloc));
- for (i=0; i < nrel; i++)
- {fread((char *)&relocation_info, sizeof(struct reloc),
- 1, fp);
- dprintf(relocating %d,i);
- relocate();
- }
- }
- #ifdef N_DRELOFF
- fseek (fp, N_DRELOFF(fileheader), 0);
- #endif
- {int nrel = (fileheader.a_drsize/sizeof(struct reloc));
- the_start += fileheader.a_text;
- for (i=0; i < nrel; i++)
-
- {fread((char *)&relocation_info, sizeof(struct reloc),
- 1, fp);
- dprintf(relocating %d,i);
- relocate();
- }
- }
- #endif
-
- /* end of relocation */
- dprintf( END OF RELOCATION \n,0);
- dprintf( invoking init function at %x, start_address)
- dprintf( textsize is %x,textsize);
- dprintf( datasize is %x,datasize);
-
- /* read in the fasl vector */
- fseek(fp,fasl_vector_start,0);
- if (feof(fp))
- {data=0;}
- else{
- data = read_fasl_vector(faslfile);
- vs_push(data);
- #ifdef COFF
- dprintf( read fasl now symbols %d , fileheader.f_nsyms);
- #endif
- }
- close_stream(faslfile, 1);
-
- /*
- {
- int fd;
-
- fd = creat ("xsakcl.bits", 0777);
- write (fd, memory->cfd.cfd_start, textsize + datasize);
- close (fd);
-
- fd = open ("xsl2.bits", 0);
- read (fd, memory->cfd.cfd_start, memory->cfd.cfd_size);
- close (fd);
- }
- */
-
- #ifndef STAND
- TEMP_FREE(my_string_table);
- TEMP_FREE(symbol_table);
-
- call_init(init_address,memory,data);
-
- vs_base = old_vs_base;
- vs_top = old_vs_top;
- if(symbol_value(Vload_verbose)!=Cnil)
- printf("start address -T %x ",memory->cfd.cfd_start);
- return(memory->cfd.cfd_size);
- #endif
- {FILE *out;
- out=fopen("/tmp/sfasltest","w");
- fwrite((char *)&fileheader, sizeof(struct filehdr), 1, out);
- fwrite(start_address,sizeof(char),datasize+textsize,out);
- fclose(out);}
- printf("\n(start %x)\n",start_address);
-
- }
-
- get_extra_bss(symbol_table,length,start,ptr)
- int length;
- struct syment *symbol_table;
- int *ptr; /* store init address offset here */
- {int result = start;
- struct syment *end,*sym;
- char tem[SYMNMLEN +1];
- end =symbol_table + length;
- for(sym=symbol_table; sym < end; sym++)
- {
- #ifdef FIND_INIT
- FIND_INIT
- #endif
- #ifdef BSD
- tem; /* ignored */
- if(SYM_EXTERNAL_P(sym) && SYM_UNDEF_P(sym))
- #endif
- #ifdef COFF
- if(0)
- /* what we really want is
- if (sym->n_scnum==0 && sym->n_sclass == C_EXT
- && !(bsearch(..in ptable for this symbol)))
- Since this won't allow loading in of a new external array
- char foo[10] not ok
- static foo[10] ok.
- for the moment we give undefined symbol warning..
- Should really go through the symbols, recording the external addr
- for ones found in ptable, and for the ones not in ptable
- set some flag, and add up the extra_bss required. Then
- when you have the new memory chunk in hand,
- you could make the pass setting the relative addresses.
- for the ones you flagged last time.
- */
- #endif
- /* external bss so not included in size of bss for file */
- {int val=sym->n_value;
- struct node joe;
- if (val && c_table.ptable)
- {joe.string=SYM_NAME(sym);
- if(0==bsearch((char *)(&joe),(char*) (c_table.ptable),
- c_table.length,
- sizeof(struct node), node_compare))
- { sym->n_value=result;
- result += val;}}}
-
- sym += NUM_AUX(sym);
-
- }
- return (result-start);
- }
-
-
-
- /* go through the symbol table changing the addresses of the symbols
- to reflect the current cfd_start */
-
- relocate_symbols(length)
- unsigned int length;
- {struct syment *end,*sym;
- unsigned int typ;
- char *str;
- char tem[SYMNMLEN +1];
- tem[SYMNMLEN]=0;
- end =symbol_table + length;
- for(sym=symbol_table; sym < end; sym++) {
- typ=NTYPE(sym);
- #ifdef BSD
- #ifdef N_STAB
- if (N_STAB & sym->n_type) continue;/* skip: It is for dbx only */
- #endif
- typ=N_SECTION(sym);
- /* if(sym->n_type & N_EXT) should add the symbol name,
- so it would be accessible by future loads */
- #endif
- switch (typ) {
- #ifdef BSD
- case N_ABS : case N_TEXT: case N_DATA: case N_BSS:
- #endif
- #ifdef COFF
- case 1: case 2: case 3:
- #endif
- str=SYM_NAME(sym);
- dprintf( for sym %s ,str)
- dprintf( new value will be start %x, start_address);
- sym->n_value = (int)start_address;
- break;
- case N_UNDEF:
- str=SYM_NAME(sym);
- dprintf( undef symbol %s ,str);
- dprintf( symbol diff %d , sym - symbol_table);
- describe_sym(sym-symbol_table);
- set_symbol_address(sym,str);
- describe_sym(sym-symbol_table);
- break;
- default:
- #ifdef COFF
- dprintf(am ignoring a scnum %d,(sym->n_scnum));
- #endif
- break;
- }
- sym += NUM_AUX(sym);
- }
- }
-
- /*
- STEPS:
- 1) read in the symbol table from the file,
- 2) go through the symbol table, relocating external entries.
- 3) for i <=2 go thru the relocation information for this section
- relocating the text.
- 4) done.
- */
-
- set_symbol_address(sym,string)
- struct syment *sym;
- char *string;
- {struct node *answ,joe;
- if (c_table.ptable)
- {joe.string=string;
- dprintf(string %s, string);
-
- answ = (struct node *)bsearch((char *)(&joe),(char*) (c_table.ptable),
- c_table.length,
- sizeof(struct node), node_compare);
- dprintf(answ %d , (answ ? answ->address : -1));
- if(answ)
- {
- #ifdef COFF
- sym->n_value = answ->address - sym->n_value;
- #endif
- #ifdef BSD
- /* the old value of sym->n_value is the length of the common area
- starting at this address */
- sym->n_value = answ->address;
- #endif
- }
- else
- {
-
- #ifdef BSD
- {char *name;
- name=malloc(1+strlen(string));
- strcpy(name,string);
- sym->n_value = sym->n_value + (unsigned int) the_start;
- add_symbol(string,sym->n_value,NULL);
- }
- #endif
- fprintf(stdout,"undefined %s symbol",string)
- ;fflush(stdout);
-
- }}
-
- else{FEerror("symbol table not loaded",0,0);}}
-
- /*
- #define ADD_SYMBOL(name) add_symbol("name",(int) &(name),0)
- Use the add_symbol to add a c symbol, which you want to refer
- to in subsequent loads. The address used in subsequent loads,
- will be the load address of the current symbol.
- Such a symbol may only be added once, since subsequent references
- will try to link to the old address.
- */
-
- build_symbol_table()
- { printf("Building symbol table for %s ..\n",kcl_self);fflush(stdout);
- sprintf(tmpfile1,"/tmp/rsym%d",getpid());
- coerce_to_filename(symbol_value(siVsystem_directory),
- system_directory);
- sprintf(command,"%srsym %s %s",system_directory,kcl_self,tmpfile1);
- if (system(command) != 0)
- FEerror("The rsym command ~a failed .",1,make_simple_string(command)
- );
- read_special_symbols(tmpfile1);
- unlink(tmpfile1);
- dprintf(c_table %d , c_table.length);
- qsort((char*)(c_table.ptable),(int)(c_table.length),sizeof(struct node),node_compare);
- }
-
-
-
- /*to do:Addition of one symbol to the ptable is very slow, because we
- sort each time! */
-
- add_symbol(va_alist)
- va_dcl
- {char *string;
- int address;
- struct node joe;
- int nstr,i;
- va_list ap;
-
- /* terminate arg list with NULL pointer */
-
- if(!(c_table.ptable)) return ; /* this is in a function before ptable is init */
- nstr=0;
- /* count the number of strings */
-
- va_start(ap);
- while (va_arg(ap,char*)!=0)
- { nstr++;
- va_arg(ap,int);
- if (nstr >1000) FEerror("Did you really give 1000 strings or just forget 0 ending",0,0);};
- va_end(ap);
-
- va_start(ap);
- if (( int)((c_table.alloc_length) - (c_table.length)) -nstr>0)
- {
- BEGIN:
- for(i=0;i<2*nstr;i=i+2)
- { string=va_arg(ap,char *);
- joe.string=string;
- if(bsearch((char *)(&joe),(char*) (c_table.ptable),(c_table.length),
- sizeof(struct node), node_compare))
- {FEerror("The string ~a is already in the ptable",1,
- make_simple_string(string));};
- {struct node *u;
- u= ((*(c_table.ptable))+((c_table.length)+(i/2)));
- u->string = string;
- u->address = va_arg(ap,int);}
- }
- (c_table.length)=(c_table.length)+nstr;
- qsort((char*)(c_table.ptable),(int)(c_table.length),sizeof(struct node),node_compare);
- }
- else
- /* grow the ptable */
- { TABL *new, *old_pt;
- new=
- (TABL *)malloc(sizeof(struct node)
- *((c_table.alloc_length)=((c_table.length) + nstr + PTABLE_EXTRA)));
- old_pt=(c_table.ptable);
- /* copy it */
- {register int i ;
- for (i=0; i < c_table.length; i++)
- {(*new)[i].string=(*old_pt)[i].string;
- (*new)[i].address=(*old_pt)[i].address;}}
-
- (c_table.ptable)=new;
- free((char *)old_pt);
- goto BEGIN ;
- }
- va_end(ap);
-
- }
-
- /* this is in fat_string.c for the moment */
- /*
- read_special_symbols(symfile)
- char *symfile;
- {FILE *symin;
- char *symbols;
- int i,jj;
- struct lsymbol_table tab;
- if (!(symin=fopen(symfile,"r")))
- {perror(symfile);exit(1);};
- fread((char *)&tab,sizeof(tab),1,symin);
- 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)
- { fread((char *)&jj,sizeof(int),1,symin);
- (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( address %d , jj);
- i++;
- }
-
- }
-
- */
-
- #ifdef DEBUG
- print_name(p)
- struct syment *p;
- {char tem[10],*name;
- name=SYM_NAME(p);
- name= (((p)->_n._n_n._n_zeroes == 0) ?
- &my_string_table[(p)->_n._n_n._n_offset] :
- ((p)->_n._n_name[SYMNMLEN -1] ?
- (strncpy(tem,(p)->_n._n_name,
- SYMNMLEN),
- (char *)tem) :
- (p)->_n._n_name ));
-
- printf("(name:|%s|)",name);
- printf("(sclass 0x%x)",p->n_sclass);
- printf("(external_p 0x%x)",SYM_EXTERNAL_P(p));
- printf("(n_type 0x%x)",p->n_type);
- printf("(n_value 0x%x)",p->n_value);
- printf("(numaux 0x%x)\n",NUM_AUX(p));
- fflush(stdout);
- }
- #endif
-