grandi@noao.UUCP (02/09/87)
: This is a shar archive. Extract with sh, not csh. echo x - Readme sed -e 's/^X//' > Readme << '!Funky!Stuff!' XDoug Tody, Chief Programmer for our Image Reduction and Analysis Facility X(IRAF) project, has optimized the 4.3BSD ld program to improve its Xperformance when it is used to link programs against large libraries. Doug's Xnotes on the modification follow: X X The main change was to read the entire symbol table of each object X module in all at once rather than a symbol at a time, which would X result in tens of thousands of calls to the mget function when linking X against large libraries. Since there are now far fewer calls to the X mget function, and the average call returns quite a bit more data, I X also rewrote mget to use bcopy (movc3 on a vax) rather than a char loop X to copy the data out to the user buffer. When possible, large object X libraries should also be reordered in topological order (e.g., with the X reorder cshell script provided) to minimize disk seeks and maximize X hits on the buffer cache. In our case, where we commonly link against X several very large libraries, these changes cut the wallclock link time X nearly in half, and reduced the cpu time consumed by ld by 15-30 X percent. X XAnother change to ld incorporated in the attached patch file is the addition Xof a Y flag which will cause information about symbols to be printed during Xrelocation. This option can occasionally come in handy when debugging. X XSteve Grandi, National Optical Astronomy Observatories, Tucson, AZ, 602-325-9228 XUUCP: {arizona,decvax,hao,ihnp4,seismo}!noao!grandi Internet: grandi@noao.arpa XSPAN/HEPNET: 5356::GRANDI or DRACO::GRANDI !Funky!Stuff! echo x - ld.diff sed -e 's/^X//' > ld.diff << '!Funky!Stuff!' X*** ld.c.ORIG Sat Jan 11 12:42:58 1986 X--- ld.c Sun Feb 8 15:58:37 1987 X*************** X*** 235,236 **** X--- 235,237 ---- X int trace; X+ int Yflag; /* print symbol info during relocation */ X int xflag; /* discard local symbols */ X*************** X*** 333,337 **** X /* X! * Base of the string table of the current module (pass1 and pass2). X */ X! char *curstr; X X--- 334,339 ---- X /* X! * Symbol table storage for the current module (pass1 and pass2). X */ X! char *symtab; /* symbol table of current module */ X! char *curstr; /* string table of current module */ X X*************** X*** 461,462 **** X--- 463,467 ---- X continue; X+ case 'Y': X+ Yflag++; X+ continue; X case 'S': X*************** X*** 800,808 **** X { X! register struct nlist *sp; X! struct nlist *savnext; X! int ndef, nlocal, type, size, nsymt; X! register int i; X! off_t maxoff; X! struct stat stb; X X readhdr(loc); X--- 805,816 ---- X { X! register struct nlist *sp, *symp, *stop; X! register int type, i; X! struct nlist *savnext; X! int ndef, nlocal, nsymt; X! int symtab_size, sbuf_size; X! struct stat stb; X! off_t maxoff; X X+ /* Read the object module header. X+ */ X readhdr(loc); X*************** X*** 813,814 **** X--- 821,825 ---- X } X+ X+ /* Determine the total size of the object module. X+ */ X if (libflg) X*************** X*** 819,820 **** X--- 830,833 ---- X } X+ X+ /* Verify that the sizes add up. */ X if (N_STROFF(filhdr) + sizeof (off_t) >= maxoff) X*************** X*** 821,824 **** X error(1, "too small (old format .o?)"); X ctrel = tsize; cdrel += dsize; cbrel += bsize; X- ndef = 0; X nlocal = sizeof(cursym); X--- 834,837 ---- X error(1, "too small (old format .o?)"); X+ X ctrel = tsize; cdrel += dsize; cbrel += bsize; X nlocal = sizeof(cursym); X*************** X*** 825,842 **** X savnext = nextsym; X loc += N_SYMOFF(filhdr); X! dseek(&text, loc, filhdr.a_syms); X! dseek(&reloc, loc + filhdr.a_syms, sizeof(off_t)); X! mget(&size, sizeof (size), &reloc); X! dseek(&reloc, loc + filhdr.a_syms+sizeof (off_t), size-sizeof (off_t)); X! curstr = (char *)malloc(size); X! if (curstr == NULL) X! error(1, "no space for string table"); X! mget(curstr+sizeof(off_t), size-sizeof(off_t), &reloc); X! while (text.size > 0) { X! mget((char *)&cursym, sizeof(struct nlist), &text); X! if (cursym.n_un.n_strx) { X! if (cursym.n_un.n_strx<sizeof(size) || X! cursym.n_un.n_strx>=size) X error(1, "bad string table index (pass 1)"); X! cursym.n_un.n_name = curstr + cursym.n_un.n_strx; X } X--- 838,869 ---- X savnext = nextsym; X+ ndef = 0; X+ X+ /* Determine the sizes of the symbol table and string buffer. X+ */ X loc += N_SYMOFF(filhdr); X! symtab_size = filhdr.a_syms; X! dseek(&reloc, loc + symtab_size, sizeof(off_t)); X! mget(&sbuf_size, sizeof(sbuf_size), &reloc); X! X! /* Allocate a buffer large enough to hold both the symbol table and X! * string buffer, and read both structures into the buffer. X! */ X! symtab = (char *)malloc(symtab_size + sbuf_size); X! if (symtab == NULL) X! error(1, "no space for symbol table"); X! curstr = symtab + symtab_size; X! dseek(&text, loc, (long)(symtab_size + sbuf_size)); X! mget(symtab, (long)(symtab_size + sbuf_size), &text); X! X! /* Examine each symbol in turn. X! */ X! symp = (struct nlist *)symtab; X! stop = symp + symtab_size / sizeof(struct nlist); X! X! for (; symp < stop; symp++) { X! cursym = *symp; X! if (i = cursym.n_un.n_strx) { X! if (i < sizeof(sbuf_size) || i >= sbuf_size) X error(1, "bad string table index (pass 1)"); X! cursym.n_un.n_name = curstr + i; X } X*************** X*** 849,851 **** X } X! symreloc(); X if (enter(lookup())) X--- 876,901 ---- X } X! X! /* Relocate symbol */ X! if (!funding) X! switch (cursym.n_type & 017) { X! case N_TEXT: X! case N_EXT+N_TEXT: X! cursym.n_value += ctrel; X! break; X! case N_DATA: X! case N_EXT+N_DATA: X! cursym.n_value += cdrel; X! break; X! case N_BSS: X! case N_EXT+N_BSS: X! cursym.n_value += cbrel; X! break; X! case N_EXT+N_UNDF: X! break; X! default: X! if (cursym.n_type&N_EXT) X! cursym.n_type = N_EXT+N_ABS; X! break; X! } X! X if (enter(lookup())) X*************** X*** 865,866 **** X--- 915,917 ---- X } X+ X if (libflg==0 || ndef) { X*************** X*** 879,881 **** X } X! free(curstr); X return (1); X--- 930,932 ---- X } X! free(symtab); X return (1); X*************** X*** 882,885 **** X } X! /* X! * No symbols defined by this library member. X * Rip out the hash table entries and reset the symbol table. X--- 933,936 ---- X } X! X! /* No symbols defined by this library member. X * Rip out the hash table entries and reset the symbol table. X*************** X*** 887,889 **** X symfree(savnext); X! free(curstr); X return(0); X--- 938,940 ---- X symfree(savnext); X! free(symtab); X return(0); X*************** X*** 1142,1147 **** X X! load2(loc) X! long loc; X { X- int size; X register struct nlist *sp; X--- 1193,1197 ---- X X! load2(oloc) X! long oloc; X { X register struct nlist *sp; X*************** X*** 1148,1153 **** X register struct local *lp; X! register int symno, i; X! int type; X X! readhdr(loc); X if (!funding) { X--- 1198,1204 ---- X register struct local *lp; X! register int symno, type, i; X! struct nlist *symp, *stop; X! int symtab_size, sbuf_size, loc; X X! readhdr(oloc); X if (!funding) { X*************** X*** 1157,1160 **** X } X! /* X! * Reread the symbol table, recording the numbering X * of symbols for fixing external references. X--- 1208,1211 ---- X } X! X! /* Reread the symbol table, recording the numbering X * of symbols for fixing external references. X*************** X*** 1166,1192 **** X symno = -1; X! loc += N_TXTOFF(filhdr); X! dseek(&text, loc+filhdr.a_text+filhdr.a_data+ X! filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms, sizeof(off_t)); X! mget(&size, sizeof(size), &text); X! dseek(&text, loc+filhdr.a_text+filhdr.a_data+ X! filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms+sizeof(off_t), X! size - sizeof(off_t)); X! curstr = (char *)malloc(size); X! if (curstr == NULL) X! error(1, "out of space reading string table (pass 2)"); X! mget(curstr+sizeof(off_t), size-sizeof(off_t), &text); X! dseek(&text, loc+filhdr.a_text+filhdr.a_data+ X! filhdr.a_trsize+filhdr.a_drsize, filhdr.a_syms); X! while (text.size > 0) { X symno++; X! mget((char *)&cursym, sizeof(struct nlist), &text); X! if (cursym.n_un.n_strx) { X! if (cursym.n_un.n_strx<sizeof(size) || X! cursym.n_un.n_strx>=size) X error(1, "bad string table index (pass 2)"); X! cursym.n_un.n_name = curstr + cursym.n_un.n_strx; X } X- /* inline expansion of symreloc() */ X- switch (cursym.n_type & 017) { X X case N_TEXT: X--- 1217,1253 ---- X symno = -1; X! X! loc = oloc + N_SYMOFF(filhdr); X! X! /* Determine the sizes of the symbol table and string buffer. X! */ X! symtab_size = filhdr.a_syms; X! dseek(&reloc, loc + symtab_size, sizeof(off_t)); X! mget(&sbuf_size, sizeof(sbuf_size), &reloc); X! X! /* Allocate a buffer large enough to hold both the symbol table and X! * string buffer, and read both structures into the buffer. X! */ X! symtab = (char *)malloc(symtab_size + sbuf_size); X! if (symtab == NULL) X! error(1, "no space for symbol table (pass 2)"); X! curstr = symtab + symtab_size; X! dseek(&text, loc, (long)(symtab_size + sbuf_size)); X! mget(symtab, (long)(symtab_size + sbuf_size), &text); X! X! /* Examine each symbol in turn. X! */ X! symp = (struct nlist *)symtab; X! stop = symp + symtab_size / sizeof(struct nlist); X! X! for (; symp < stop; symp++) { X! cursym = *symp; X symno++; X! if (i = cursym.n_un.n_strx) { X! if (i < sizeof(sbuf_size) || i >= sbuf_size) X error(1, "bad string table index (pass 2)"); X! cursym.n_un.n_name = curstr + i; X } X X+ /* Relocate symbol */ X+ switch (cursym.n_type & 017) { X case N_TEXT: X*************** X*** 1209,1211 **** X } X! /* end inline expansion of symreloc() */ X type = cursym.n_type; X--- 1270,1272 ---- X } X! X type = cursym.n_type; X*************** X*** 1255,1256 **** X--- 1316,1318 ---- X } X+ X if (funding) X*************** X*** 1257,1258 **** X--- 1319,1322 ---- X return; X+ X+ loc = oloc + N_TXTOFF(filhdr); X dseek(&text, loc, filhdr.a_text); X*************** X*** 1260,1261 **** X--- 1324,1326 ---- X load2td(ctrel, torigin - textbase, tout, trout); X+ X dseek(&text, loc+filhdr.a_text, filhdr.a_data); X*************** X*** 1264,1265 **** X--- 1329,1331 ---- X load2td(cdrel, dorigin - database, dout, drout); X+ X while (filhdr.a_data & (sizeof(long)-1)) { X*************** X*** 1271,1273 **** X borigin += round(filhdr.a_bss, sizeof (long)); X! free(curstr); X } X--- 1337,1339 ---- X borigin += round(filhdr.a_bss, sizeof (long)); X! free(symtab); X } X*************** X*** 1313,1314 **** X--- 1379,1409 ---- X X+ d_tracesym (sp) X+ register struct nlist *sp; X+ { X+ register struct tynames *tp; X+ X+ if (sp->n_type & N_STAB) X+ return; X+ /* printf("ld:%s", filname); */ X+ if (archdr.ar_name[0]) X+ printf("(%s)", archdr.ar_name); X+ printf(": "); X+ if ((sp->n_type&N_TYPE) == N_UNDF && sp->n_value) { X+ printf("common %s size %d\n", X+ sp->n_un.n_name, sp->n_value); X+ return; X+ } X+ for (tp = tynames; tp->ty_name; tp++) X+ if (tp->ty_value == (sp->n_type&N_TYPE)) X+ break; X+ printf((sp->n_type&N_TYPE) ? "" : "reference to"); X+ /* X+ * if (sp->n_type&N_EXT) X+ * printf(" external"); X+ */ X+ if (tp->ty_name) X+ printf(" %s", tp->ty_name); X+ printf(" %s\n", sp->n_un.n_name); X+ } X+ X /* X*************** X*** 1390,1391 **** X--- 1485,1488 ---- X sp = lp->l_symbol; X+ if (Yflag) X+ d_tracesym (sp); X if (sp->n_type == N_EXT+N_UNDF) X*************** X*** 1511,1516 **** X mget(loc, n, sp) X register STREAM *sp; X- register char *loc; X { X- register char *p; X register int take; X--- 1608,1613 ---- X mget(loc, n, sp) X+ register char *loc; X+ register int n; X register STREAM *sp; X { X register int take; X*************** X*** 1520,1523 **** X return; X if (sp->size && sp->nibuf) { X- p = sp->ptr; X take = sp->size; X--- 1617,1620 ---- X return; X+ X if (sp->size && sp->nibuf) { X take = sp->size; X*************** X*** 1527,1528 **** X--- 1624,1626 ---- X take = n; X+ X n -= take; X*************** X*** 1531,1536 **** X sp->pos += take; X! do X! *loc++ = *p++; X! while (--take > 0); X! sp->ptr = p; X goto top; X--- 1629,1634 ---- X sp->pos += take; X! bcopy (sp->ptr, loc, take); X! sp->ptr += take; X! loc += take; X! X goto top; X*************** X*** 1537,1538 **** X--- 1635,1637 ---- X } X+ X if (n > p_blksize) { X*************** X*** 1549,1550 **** X--- 1648,1650 ---- X } X+ X *loc++ = get(sp); X*************** X*** 1841,1872 **** X /*NOTREACHED*/ X- } X- X- symreloc() X- { X- if(funding) return; X- switch (cursym.n_type & 017) { X- X- case N_TEXT: X- case N_EXT+N_TEXT: X- cursym.n_value += ctrel; X- return; X- X- case N_DATA: X- case N_EXT+N_DATA: X- cursym.n_value += cdrel; X- return; X- X- case N_BSS: X- case N_EXT+N_BSS: X- cursym.n_value += cbrel; X- return; X- X- case N_EXT+N_UNDF: X- return; X- X- default: X- if (cursym.n_type&N_EXT) X- cursym.n_type = N_EXT+N_ABS; X- return; X- } X } X--- 1941,1942 ---- !Funky!Stuff! echo x - reorder sed -e 's/^X//' > reorder << '!Funky!Stuff!' X# REORDER -- Reorder a library in topological order. X# X# usage: reorder libXXX.a X# X# Makes a temporary subdirectory (__RAR) to do the the operation in. If a X# second call is made before the first finishes, the second will wait. X Xwhile (-e __RAR) X sleep 10 Xend X Xmkdir __RAR Xln -s $1 __RAR.olib.a Xcd __RAR X Xar xo ../__RAR.olib.a Xrm __.SYMDEF >& /dev/null Xar cq _lib.a `lorder *.o | tsort` Xranlib _lib.a X Xcd .. Xmv -f __RAR/_lib.a $1 Xrm -r __RAR.olib.a __RAR !Funky!Stuff! exit -- Steve Grandi, National Optical Astronomy Observatories, Tucson, AZ, 602-325-9228 UUCP: {arizona,decvax,hao,ihnp4,seismo}!noao!grandi Internet: grandi@noao.arpa SPAN/HEPNET: 5356::GRANDI or DRACO::GRANDI