Efficiency Improvement for 4.3BSD ld

grandi at noao.UUCP grandi at noao.UUCP
Mon Feb 9 10:00:45 AEST 1987


: 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 at 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 at noao.arpa
SPAN/HEPNET: 5356::GRANDI or DRACO::GRANDI



More information about the Comp.bugs.4bsd.ucb-fixes mailing list