⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ld.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
		sp = xsym(i);		switch (sp->n_type & (N_TYPE+N_EXT)) {		case N_EXT+N_UNDF:			if (arflag == 0)				errlev |= 01;			if ((arflag==0 || dflag) && sp->n_value==0) {				if (sp==p_end || sp==p_etext || sp==p_edata)					continue;				if (nund==0)					printf("Undefined:\n");				nund++;				printf("%s\n", sp->n_un.n_name);			}			continue;		case N_EXT+N_ABS:		default:			continue;		case N_EXT+N_TEXT:			sp->n_value += torigin;			continue;		case N_EXT+N_DATA:			sp->n_value += dorigin;			continue;		case N_EXT+N_BSS:			sp->n_value += borigin;			continue;		case N_EXT+N_COMM:			sp->n_type = (sp->n_type & N_STAB) | (N_EXT+N_BSS);			sp->n_value += corigin;			continue;		}	}	if (sflag || xflag)		ssize = 0;	bsize += csize;	nsym = ssize / (sizeof cursym);	if (Aflag) {		fixspec(p_etext,torigin);		fixspec(p_edata,dorigin);		fixspec(p_end,borigin);	}}fixspec(sym,offset)	struct nlist *sym;	long offset;{	if(symx(sym) < symx(addsym) && sym!=0)		sym->n_value += offset;}ldrsym(sp, val, type)	register struct nlist *sp;	long val;{	if (sp == 0)		return;	if ((sp->n_type != N_EXT+N_UNDF || sp->n_value) && !Aflag) {		printf("%s: ", sp->n_un.n_name);		error(0, "user attempt to redfine loader-defined symbol");		return;	}	sp->n_type = type;	sp->n_value = val;}off_t	wroff;struct	biobuf toutb;setupout(){	int bss;	struct stat stbuf;	extern char *sys_errlist[];	extern int errno;	ofilemode = 0777 & ~umask(0);	biofd = creat(ofilename, 0666 & ofilemode);	if (biofd < 0) {		filname = ofilename;		/* kludge */		archdr.ar_name[0] = 0;		/* kludge */		error(1, sys_errlist[errno]);	/* kludge */		/* NOT REACHED */	}	fstat(biofd, &stbuf);		/* suppose file exists, wrong*/	if (stbuf.st_mode & 0111) {	/* mode, ld fails? */		chmod(ofilename, stbuf.st_mode & 0666);		ofilemode = stbuf.st_mode;	}	filhdr.a_magic = nflag ? NMAGIC : (zflag ? ZMAGIC : OMAGIC);	filhdr.a_mode = (ex_mode == sys_v) ? A_SYSV : 		((ex_mode == posix) ? A_POSIX : A_BSD);	filhdr.a_text = nflag ? tsize :	    round(tsize, zflag ? pagesize : sizeof (long));	filhdr.a_data = zflag ? round(dsize, pagesize) : dsize;	bss = bsize - (filhdr.a_data - dsize);	if (bss < 0)		bss = 0;	filhdr.a_bss = bss;	filhdr.a_trsize = trsize;	filhdr.a_drsize = drsize;	if (sflag) {	    filhdr.a_syms = 0;	} else {	    filhdr.a_syms = ssize + (sizeof cursym)*symx(nextsym);	    /* There are three extra nlist entries added at the beginning	     * of the symbol table containing counts (see nsline, nfun)	     * for dbx, if the program was linked "-lg".  (vjh)	     */	    if (gflag) {	        filhdr.a_syms += (3 * sizeof(struct nlist));	    }	}	if (entrypt) {		if (entrypt->n_type!=N_EXT+N_TEXT)			error(0, "entry point not in text");		else			filhdr.a_entry = entrypt->n_value;	} else		filhdr.a_entry = 0;	filhdr.a_trsize = (rflag ? trsize:0);	filhdr.a_drsize = (rflag ? drsize:0);	tout = &toutb;	bopen(tout, 0, stbuf.st_blksize);	bwrite((char *)&filhdr, sizeof (filhdr), tout);	if (zflag)		bseek(tout, pagesize);	wroff = N_TXTOFF(filhdr) + filhdr.a_text;	outb(&dout, filhdr.a_data, stbuf.st_blksize);	if (rflag) {		outb(&trout, filhdr.a_trsize, stbuf.st_blksize);		outb(&drout, filhdr.a_drsize, stbuf.st_blksize);	}	if (sflag==0 || xflag==0) {		outb(&sout, filhdr.a_syms, stbuf.st_blksize);		wroff += sizeof (offset);		outb(&strout, 0, stbuf.st_blksize);		if (gflag) {		    outstabcnt();		}	}}/* Routine to output the number of functions, source lines, and * source files.  These records *must* be the first three records in * the symbol table, and are used by dbx in estimating the size of * some tables that it has to build.  This information is present * only if -lg was specified. (vjh) */outstabcnt(){    struct nlist stabcnt;    if (sflag || xflag) return;		/* 005 - vjh */    stabcnt.n_type = N_NSYMS;    stabcnt.n_un.n_name = 0;    stabcnt.n_desc = 0;    stabcnt.n_other = 0;    stabcnt.n_value = nsol;    /* This will be the first record in the symbol table. */    bwrite(&stabcnt, sizeof(stabcnt), sout);    stabcnt.n_value = nfun;    /* This will be the second record in the symbol table. */    bwrite(&stabcnt, sizeof(stabcnt), sout);    stabcnt.n_value = nsline;    /* This will be the third record in the symbol table. */    bwrite(&stabcnt, sizeof(stabcnt), sout);}outb(bp, inc, bufsize)	register struct biobuf **bp;{	*bp = (struct biobuf *)malloc(sizeof (struct biobuf));	if (*bp == 0)		error(1, "ran out of memory (outb)");	bopen(*bp, wroff, bufsize);	wroff += inc;}load2arg(acp)char *acp;{	register char *cp;	off_t loc;	cp = acp;	if (getfile(cp) == 0) {		while (*cp)			cp++;		while (cp >= acp && *--cp != '/');		mkfsym(++cp);		load2(0L);	} else {	/* scan archive members referenced */		for (;;) {			if (clibseg->li_used2 == clibseg->li_used) {				if (clibseg->li_used < NROUT)					error(1, "libseg botch");				clibseg++;			}			loc = clibseg->li_first[clibseg->li_used2++];			if (loc == -1)				break;			dseek(&text, loc, (long)sizeof(archdr));			getarhdr();			mkfsym(archdr.ar_name);			load2(loc + (long)sizeof(archdr));		}	}	close(infil);}load2(loc)long loc;{	int size;	register struct nlist *sp;	register struct local *lp;	register int symno, i;	int type;	readhdr(loc);	if (!funding) {		ctrel = torigin;		cdrel += dorigin;		cbrel += borigin;	}	/*	 * Reread the symbol table, recording the numbering	 * of symbols for fixing external references.	 */	for (i = 0; i < LHSIZ; i++)		lochash[i] = 0;	clocseg = locseg;	clocseg->lo_used = 0;	symno = -1;	loc += N_TXTOFF(filhdr);	dseek(&text, loc+filhdr.a_text+filhdr.a_data+		filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms, sizeof(off_t));	mget(&size, sizeof(size), &text);	dseek(&text, loc+filhdr.a_text+filhdr.a_data+		filhdr.a_trsize+filhdr.a_drsize+filhdr.a_syms+sizeof(off_t),		size - sizeof(off_t));	curstr = (char *)malloc(size);	if (curstr == NULL)		error(1, "out of space reading string table (pass 2)");	mget(curstr+sizeof(off_t), size-sizeof(off_t), &text);	dseek(&text, loc+filhdr.a_text+filhdr.a_data+		filhdr.a_trsize+filhdr.a_drsize, filhdr.a_syms);	while (text.size > 0) {		symno++;		mget((char *)&cursym, sizeof(struct nlist), &text);		if (cursym.n_un.n_strx) {			if (cursym.n_un.n_strx<sizeof(size) ||			    cursym.n_un.n_strx>=size)				error(1, "bad string table index (pass 2)");			cursym.n_un.n_name = curstr + cursym.n_un.n_strx;		}/* inline expansion of symreloc() */		switch (cursym.n_type & 017) {		case N_TEXT:		case N_EXT+N_TEXT:			cursym.n_value += ctrel;			break;		case N_DATA:		case N_EXT+N_DATA:			cursym.n_value += cdrel;			break;		case N_BSS:		case N_EXT+N_BSS:			cursym.n_value += cbrel;			break;		case N_EXT+N_UNDF:			break;		default:			if (cursym.n_type&N_EXT)				cursym.n_type = N_EXT+N_ABS;		}/* end inline expansion of symreloc() */		type = cursym.n_type;		if (yflag && cursym.n_un.n_name)			for (i = 0; i < yflag; i++)				/* fast check for 2d character! */				if (ytab[i][1] == cursym.n_un.n_name[1] &&				    !strcmp(ytab[i], cursym.n_un.n_name)) {					tracesym();					break;				}		if ((type&N_EXT) == 0) {			if (!sflag&&!xflag&&		/* SLR001 */			    (!Xflag||type&N_STAB||cursym.n_un.n_name[0]!='L'))				symwrite(&cursym, sout);			continue;		}		if (funding)			continue;		if ((sp = *lookup()) == 0)			error(1, "internal error: symbol not found");		if (cursym.n_type == N_EXT+N_UNDF) {			if (clocseg->lo_used == NSYMPR) {				if (++clocseg == &locseg[NSEG])					error(1, "local symbol overflow");				clocseg->lo_used = 0;			}			if (clocseg->lo_first == 0) {				clocseg->lo_first = (struct local *)				    malloc(NSYMPR * sizeof (struct local));				if (clocseg->lo_first == 0)					error(1, "out of memory (clocseg)");			}			lp = &clocseg->lo_first[clocseg->lo_used++];			lp->l_index = symno;			lp->l_symbol = sp;			lp->l_link = lochash[symno % LHSIZ];			lochash[symno % LHSIZ] = lp;			continue;		}		if (cursym.n_type & N_STAB)			continue;		if (cursym.n_type!=sp->n_type || cursym.n_value!=sp->n_value) {			printf("%s: ", cursym.n_un.n_name);			error(0, "multiply defined");		}	}	if (funding)		return;	dseek(&text, loc, filhdr.a_text);	dseek(&reloc, loc+filhdr.a_text+filhdr.a_data, filhdr.a_trsize);	load2td(ctrel, torigin - textbase, tout, trout);	dseek(&text, loc+filhdr.a_text, filhdr.a_data);	dseek(&reloc, loc+filhdr.a_text+filhdr.a_data+filhdr.a_trsize,	    filhdr.a_drsize);	load2td(cdrel, dorigin - database, dout, drout);	while (filhdr.a_data & (sizeof(long)-1)) {		bputc(0, dout);		filhdr.a_data++;	}	torigin += filhdr.a_text;	dorigin += round(filhdr.a_data, sizeof (long));	borigin += round(filhdr.a_bss, sizeof (long));	free(curstr);}struct tynames {	int	ty_value;	char	*ty_name;} tynames[] = {	N_UNDF,	"undefined",	N_ABS,	"absolute",	N_TEXT,	"text",	N_DATA,	"data",	N_BSS,	"bss",	N_COMM,	"common",	0,	0,};tracesym(){	register struct tynames *tp;	if (cursym.n_type & N_STAB)		return;	printf("%s", filname);	if (archdr.ar_name[0])		printf("(%s)", archdr.ar_name);	printf(": ");	if ((cursym.n_type&N_TYPE) == N_UNDF && cursym.n_value) {		printf("definition of common %s size %d\n",		    cursym.n_un.n_name, cursym.n_value);		return;	}	for (tp = tynames; tp->ty_name; tp++)		if (tp->ty_value == (cursym.n_type&N_TYPE))			break;	printf((cursym.n_type&N_TYPE) ? "definition of" : "reference to");	if (cursym.n_type&N_EXT)		printf(" external");	if (tp->ty_name)		printf(" %s", tp->ty_name);	printf(" %s\n", cursym.n_un.n_name);}/* * This routine relocates the single text or data segment argument. * Offsets from external symbols are resolved by adding the value * of the external symbols.  Non-external reference are updated to account * for the relative motion of the segments (ctrel, cdrel, ...).  If * a relocation was pc-relative, then we update it to reflect the * change in the positioning of the segments by adding the displacement * of the referenced segment and subtracting the displacement of the * current segment (creloc). * * If we are saving the relocation information, then we increase * each relocation datum address by our base position in the new segment. */load2td(creloc, position, b1, b2)	long creloc, position;					/* DLB002 */	struct biobuf *b1, *b2;{	register struct nlist *sp;	register struct local *lp;	long tw;	register struct relocation_info *rp, *rpend;	struct relocation_info *relp;	char *codep;	register char *cp;	int relsz, codesz;	relsz = reloc.size;	relp = (struct relocation_info *)malloc(relsz);	codesz = text.size;	codep = (char *)malloc(codesz);	if (relp == 0 || codep == 0)		error(1, "out of memory (load2td)");	mget((char *)relp, relsz, &reloc);	rpend = &relp[relsz / sizeof (struct relocation_info)];	mget(codep, codesz, &text);	for (rp = relp; rp < rpend; rp++) {		cp = codep + rp->r_address;		/*		 * Pick up previous value at location to be relocated.		 */		switch (rp->r_length) {		case 0:		/* byte */			tw = *cp;			break;		case 1:		/* word */			tw = *(short *)cp;			break;		case 2:		/* long */			tw = *(long *)cp;			break;		default:			error(1, "load2td botch: bad length");		}		/*		 * If relative to an external which is defined,		 * resolve to a simpler kind of reference in the		 * result file.  If the external is undefined, just		 * convert the symbol number to the number of the		 * symbol in the result file and leave it undefined.		 */		if (rp->r_extern) {			/*			 * Search the hash table which maps local			 * symbol numbers to symbol tables entries			 * in the new a.out file.			 */			lp = lochash[rp->r_symbolnum % LHSIZ];			while (lp->l_index != rp->r_symbolnum) {				lp = lp->l_link;				if (lp == 0)					error(1, "local symbol botch");			}			sp = lp->l_symbol;			if (sp->n_type == N_EXT+N_UNDF)				rp->r_symbolnum = nsym+symx(sp);			else {				rp->r_symbolnum = sp->n_type & N_TYPE;				tw += sp->n_value;				rp->r_extern = 0;			}		} else switch (rp->r_symbolnum & N_TYPE) {		/*		 * Relocation is relative to the loaded position		 * of another segment.  Update by the change in position		 * of that segment.		 */		case N_TEXT:			tw += ctrel;			break;		case N_DATA:			tw += cdrel;			break;		case N_BSS:			tw += cbrel;			break;		case N_ABS:			break;		default:			error(1, "relocation format botch (symbol type))");		}		/*		 * Relocation is pc relative, so decrease the relocation		 * by the amount the current segment is displaced.		 * (E.g if we are a relative reference to a text location		 * from data space, we added the increase in the text address		 * above, and subtract the increase in our (data) address		 * here, leaving the net change the relative change in the		 * positioning of our text and data segments.)		 */		if (rp->r_pcrel)			tw -= creloc;		/*		 * Put the value back in the segment,		 * while checking for overflow.		 */		switch (rp->r_length) {		case 0:		/* byte */			if (tw < -128 || tw > 127)				error(0, "byte displacement overflow");			*cp = tw;			break;		case 1:		/* word */			if (tw < -32768 || tw > 32767)				error(0, "word displacement overflow");			*(short *)cp = tw;			break;		case 2:		/* long */			*(long *)cp = tw;			break;		}		/*		 * If we are saving relocation information,		 * we must convert the address in the segment from		 * the old .o file into an address in the segment in		 * the new a.out, by adding the position of our		 * segment in the new larger segment.		 */		if (rflag)			rp->r_address += position;	}	bwrite(codep, codesz, b1);	if (rflag)		bwrite(relp, relsz, b2);	free((char *)relp);	free(codep);}finishout(){	register int i;	int nsymt;	if (sflag==0) {		nsymt = symx(nextsym);		for (i = 0; i < nsymt; i++)			symwrite(xsym(i), sout);		bwrite(&offset, sizeof offset, sout);	}	if (!ofilfnd) {		unlink("a.out");		if (link("l.out", "a.out") < 0)			error(1, "cannot move l.out to a.out");		ofilename = "a.out";	}	delarg = errlev;	delexit();}mkfsym(s)char *s;{	if (sflag || xflag)		return;	cursym.n_un.n_name = s;	cursym.n_type = N_TEXT;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -