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

📄 ld.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 1980 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#ifndef lintchar copyright[] ="@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n";#endif#ifndef lintstatic char *sccsid = "@(#)ld.c	4.4	ULTRIX		9/17/90";#endif/************************************************************************ *									* *			Copyright (c) 1985, 1987, 1988 by		* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//************************************************************************ *									* *			Modification History				* *									* * 014	Ken Lesniak, 05-Dec-89						* *	Added Bflag to tell ld to force BSS to start on a 512 byte	* *	(hardware page) boundary.					* *									* * 013	Mark Parenti, 08-Jun-88						* *	Changed signal handlers to void.				* *									* * 012	Jon Reeves, 24-Nov-87						* *	Add logic for execution mode (a_mode field).			* *									* * 011	Jon Reeves, 05-Aug-87						* *	Don't scribble on start of string table when the link includes	* *	a null file by name.						* *									* * 010	Jon Reeves, 01-Jun-87						* *	Incorporate 4.3 changes (mostly -L option)			* *									* * 009	Jon Reeves, 01-Jun-87						* *	Don't make -r output executable unless -d present.  Avoids	* *	user errors and increases X/OPEN compliance.			* *									* * 008  Victoria Holt, 01-Jul-86					* *	Now output 3 N_NSYMS records, using stabcnt.n_value field only,	* *	to avoid possible overflow.					* *									* * 007	Victoria Holt, 23-Dec-85					* *	Bug fix:  increment nfun counter for local routines (see	* *	vjh007 in source).						* *									* * 006  Robert Rodriguez, 15-Sep-85                                     * *	Add 4.3 speed ups (subsumed in 010)				* *									* * 005  Victoria Holt, 29-Aug-85					* *	Big fix:  ld output N_NSYMS record when -x switch was specified.* *	Harmless, but shouldn't have been there by definition of the	* *	switch.								* *									* * 004  Victoria Holt, 14-Jun-85					* *	ld will now count the number of functions, source lines, and	* *	source files; this information is output in a stab record of	* *	type N_NSYMS for use by dbx.  It must be the first stab entry	* *	in the symbol table.						* *									* *	David L Ballenger, 17-May-1985					* * 003	Fix for QPR-00078.  The -H option did not work properly.  The	* *	size argument was being used to increase the base address for	* *	the data section, but the textsize written to the a.out header	* *	was not increased accordingly.					* *									* * 002- David L Ballenger, 07-Sep-84					* *	Fix error with definiton of "position" formal parameter for	* *	load2td function.						* *									* *	Stephen Reilly, 15-Feb-84					* * 001- Fix some dereferencing of NULL pointers (partially subsumed in	* *	010).								* *									* ************************************************************************//* * ld - string table version for VAX */#include <sys/param.h>#include <signal.h>#include <strings.h>#include <stdio.h>#include <ctype.h>#include <ar.h>#include <a.out.h>#include <stab.h>#include <ranlib.h>#include <sys/stat.h>#include <sys/file.h>/* * Basic strategy: * * The loader takes a number of files and libraries as arguments. * A first pass examines each file in turn.  Normal files are * unconditionally loaded, and the (external) symbols they define and require * are noted in the symbol table.   Libraries are searched, and the * library members which define needed symbols are remembered * in a special data structure so they can be selected on the second * pass.  Symbols defined and required by library members are also * recorded. * * After the first pass, the loader knows the size of the basic text * data, and bss segments from the sum of the sizes of the modules which * were required.  It has computed, for each ``common'' symbol, the * maximum size of any reference to it, and these symbols are then assigned * storage locations after their sizes are appropriately rounded. * The loader now knows all sizes for the eventual output file, and * can determine the final locations of external symbols before it * begins a second pass. * * On the second pass each normal file and required library member * is processed again.  The symbol table for each such file is * reread and relevant parts of it are placed in the output.  The offsets * in the local symbol table for externally defined symbols are recorded * since relocation information refers to symbols in this way. * Armed with all necessary information, the text and data segments * are relocated and the result is placed in the output file, which * is pasted together, ``in place'', by writing to it in several * different places concurrently. *//* * Internal data structures * * All internal data structures are segmented and dynamically extended. * The basic structures hold 1103 (NSYM) symbols, ~~200 (NROUT) * referenced library members, and 100 (NSYMPR) private (local) symbols * per object module.  For large programs and/or modules, these structures * expand to be up to 40 (NSEG) times as large as this as necessary. */#define	NSEG	40		/* Number of segments, each data structure */#define	NSYM	1103		/* Number of symbols per segment */#define	NROUT	250		/* Number of library references per segment */#define	NSYMPR	100		/* Number of private symbols per segment *//* * Structure describing each symbol table segment. * Each segment has its own hash table.  We record the first * address in and first address beyond both the symbol and hash * tables, for use in the routine symx and the lookup routine respectively. * The symfree routine also understands this structure well as it used * to back out symbols from modules we decide that we don't need in pass 1. * * Csymseg points to the current symbol table segment; * csymseg->sy_first[csymseg->sy_used] is the next symbol slot to be allocated, * (unless csymseg->sy_used == NSYM in which case we will allocate another * symbol table segment first.) */struct	symseg {	struct	nlist *sy_first;	/* base of this alloc'ed segment */	struct	nlist *sy_last;		/* end of this segment, for n_strx */	int	sy_used;		/* symbols used in this seg */	struct	nlist **sy_hfirst;	/* base of hash table, this seg */	struct	nlist **sy_hlast;	/* end of hash table, this seg */} symseg[NSEG], *csymseg;/* * The lookup routine uses quadratic rehash.  Since a quadratic rehash * only probes 1/2 of the buckets in the table, and since the hash * table is segmented the same way the symbol table is, we make the * hash table have twice as many buckets as there are symbol table slots * in the segment.  This guarantees that the quadratic rehash will never * fail to find an empty bucket if the segment is not full and the * symbol is not there. */#define	HSIZE	(NSYM*2)/* * Xsym converts symbol table indices (ala x) into symbol table pointers. * Symx (harder, but never used in loops) inverts pointers into the symbol * table into indices using the symseg[] structure. */#define	xsym(x)	(symseg[(x)/NSYM].sy_first+((x)%NSYM))/* symx() is a function, defined below */struct	nlist cursym;		/* current symbol */struct	nlist *lastsym;		/* last symbol entered */struct	nlist *nextsym;		/* next available symbol table entry */struct	nlist *addsym;		/* first sym defined during incr load */int	nsym;			/* pass2: number of local symbols in a.out *//* nsym + symx(nextsym) is the symbol table size during pass2 */struct	nlist **lookup(), **slookup();struct	nlist *p_etext, *p_edata, *p_end, *entrypt;/* * Definitions of segmentation for library member table. * For each library we encounter on pass 1 we record pointers to all * members which we will load on pass 2.  These are recorded as offsets * into the archive in the library member table.  Libraries are * separated in the table by the special offset value -1. */off_t	li_init[NROUT];struct	libseg {	off_t	*li_first;	int	li_used;	int	li_used2;} libseg[NSEG] = {	li_init, 0, 0,}, *clibseg = libseg;/* * In processing each module on pass 2 we must relocate references * relative to external symbols.  These references are recorded * in the relocation information as relative to local symbol numbers * assigned to the external symbols when the module was created. * Thus before relocating the module in pass 2 we create a table * which maps these internal numbers to symbol table entries. * A hash table is constructed, based on the local symbol table indices, * for quick lookup of these symbols. */#define	LHSIZ	31struct	local {	int	l_index;		/* index to symbol in file */	struct	nlist *l_symbol;	/* ptr to symbol table */	struct	local *l_link;		/* hash link */} *lochash[LHSIZ], lhinit[NSYMPR];struct	locseg {	struct	local *lo_first;	int	lo_used;} locseg[NSEG] = {	lhinit, 0}, *clocseg;/* * Libraries are typically built with a table of contents, * which is the first member of a library with special file * name __.SYMDEF and contains a list of symbol names * and with each symbol the offset of the library member which defines * it.  The loader uses this table to quickly tell which library members * are (potentially) useful.  The alternative, examining the symbol * table of each library member, is painfully slow for large archives. * * See <ranlib.h> for the definition of the ranlib structure and an * explanation of the __.SYMDEF file format. */int	tnum;		/* number of symbols in table of contents */int	ssiz;		/* size of string table for table of contents */struct	ranlib *tab;	/* the table of contents (dynamically allocated) */char	*tabstr;	/* string table for table of contents *//* * We open each input file or library only once, but in pass2 we * (historically) read from such a file at 2 different places at the * same time.  These structures are remnants from those days, * and now serve only to catch ``Premature EOF''. * In order to make I/O more efficient, we provide routines which * use the optimal block size returned by stat(). */#define BLKSIZE 1024typedef struct {	short	*fakeptr;	int	bno;	int	nibuf;	int	nuser;	char	*buff;	int	bufsize;} PAGE;PAGE	page[2];int	p_blksize;int	p_blkshift;int	p_blkmask;struct {	short	*fakeptr;	int	bno;	int	nibuf;	int	nuser;} fpage;typedef struct {	char	*ptr;	int	bno;	int	nibuf;	long	size;	long	pos;	PAGE	*pno;} STREAM;STREAM	text;STREAM	reloc;/* * Header from the a.out and the archive it is from (if any). */struct	exec filhdr;struct	ar_hdr archdr;#define	OARMAG 0177545/* * Options. */int	trace;int	xflag;		/* discard local symbols */int	Xflag;		/* discard locals starting with 'L' */int	Sflag;		/* discard all except locals and globals*/int	rflag;		/* preserve relocation bits, don't define common */int	arflag;		/* original copy of rflag */int	sflag;		/* discard all symbols */int	Mflag;		/* print rudimentary load map */int	nflag;		/* pure procedure */int	dflag;		/* define common even with rflag */int	zflag;		/* demand paged  */long	hsize;		/* size of hole at beginning of data to be squashed */int	Bflag;		/* set if want 512 byte alignment on BSS */int	Aflag;		/* doing incremental load */int	Nflag;		/* want impure a.out */int	funding;	/* reading fundamental file for incremental load */int	yflag;		/* number of symbols to be traced */int	gflag;		/* link for debugging */char	**ytab;		/* the symbols */enum	Mode {	sys_v, posix, bsd}	ex_mode = bsd;	/* 012 - execution mode; changed by -Y/PROG_ENV *//* * These are the cumulative sizes, set in pass 1, which * appear in the a.out header when the loader is finished. */off_t	tsize, dsize, bsize, trsize, drsize, ssize;/* Number of functions (estimate), number of source lines, and * number of source files.  This information is provided for dbx. * and is used when gflag is true (when linking -lg). (vjh) */unsigned long nsline;unsigned long nfun;unsigned long nsol;/* * Symbol relocation: c?rel is a scale factor which is * added to an old relocation to convert it to new units; * i.e. it is the difference between segment origins. * (Thus if we are loading from a data segment which began at location * 4 in a .o file into an a.out where it will be loaded starting at * 1024, cdrel will be 1020.) */long	ctrel, cdrel, cbrel;/* * Textbase is the start address of all text, 0 unless given by -T. * Database is the base of all data, computed before and used during pass2. */long	textbase, database;/* * The base addresses for the loaded text, data and bss from the * current module during pass2 are given by torigin, dorigin and borigin. */long	torigin, dorigin, borigin;/* * Errlev is nonzero when errors have occured. * Delarg is an implicit argument to the routine delexit * which is called on error.  We do ``delarg = errlev'' before normal * exits, and only if delarg is 0 (i.e. errlev was 0) do we make the * result file executable. */int	errlev;int	delarg	= 4;/* * The biobuf structure and associated routines are used to write * into one file at several places concurrently.  Calling bopen * with a biobuf structure sets it up to write ``biofd'' starting * at the specified offset.  You can then use ``bwrite'' and/or ``bputc'' * to stuff characters in the stream, much like ``fwrite'' and ``fputc''. * Calling bflush drains all the buffers and MUST be done before exit. */struct	biobuf {	short	b_nleft;		/* Number free spaces left in b_buf *//* Initialize to be less than b_bufsize initially, to boundary align in file */	char	*b_ptr;			/* Next place to stuff characters */	char	*b_buf;			/* Pointer to the buffer */	int	b_bufsize;		/* Size of the buffer */	off_t	b_off;			/* Current file offset */	struct	biobuf *b_link;		/* Link in chain for bflush() */} *biobufs;#define	bputc(c,b) ((b)->b_nleft ? (--(b)->b_nleft, *(b)->b_ptr++ = (c)) \		       : bflushc(b, c))int	biofd;off_t	boffset;struct	biobuf *tout, *dout, *trout, *drout, *sout, *strout;/* * Offset is the current offset in the string file. * Its initial value reflects the fact that we will * eventually stuff the size of the string table at the * beginning of the string table (i.e. offset itself!). */off_t	offset = sizeof (off_t);int	ofilfnd;		/* -o given; otherwise move l.out to a.out */char	*ofilename = "l.out";int	ofilemode;		/* respect umask even for unsucessful ld's */int	infil;			/* current input file descriptor */char	*filname;		/* and its name */#define	NDIRS	25#define NDEFDIRS 3		/* number of default directories in dirs[] */char	*dirs[NDIRS];		/* directories for library search */int	ndir;			/* number of directories *//* * Base of the string table of the current module (pass1 and pass2). */char	*curstr;/* * System software page size, as returned by getpagesize. */int	pagesize;char 	get();void	delexit();char	*savestr();char	*malloc();char	*getenv();main(argc, argv)char **argv;{	register int c, i; 	int num;	register char *ap, **p;	char *pep;	char save;	if (signal(SIGINT, SIG_IGN) != SIG_IGN) {		signal(SIGINT, delexit);		signal(SIGTERM, delexit);	}	if (argc == 1)		exit(4);	pagesize = getpagesize();	if ( strcmp("SYSTEM_FIVE",pep=getenv("PROG_ENV")) == 0)		ex_mode = sys_v;	else if ( strcmp("POSIX",pep) == 0)		ex_mode = posix;	else if ( strcmp("BSD",pep) == 0)		ex_mode = bsd;	/* 	 * Pull out search directories.	 */	for (c = 1; c < argc; c++) {		ap = argv[c];		if (ap[0] == '-' && ap[1] == 'L') {			if (ap[2] == 0)				error(1, "-L: pathname missing");			if (ndir >= NDIRS - NDEFDIRS)				error(1, "-L: too many directories");			dirs[ndir++] = &ap[2];		}	}	/* add default search directories */	dirs[ndir++] = "/lib";	dirs[ndir++] = "/usr/lib";	dirs[ndir++] = "/usr/local/lib";	p = argv+1;	/*	 * Scan files once to find where symbols are defined.	 */	for (c=1; c<argc; c++) {		if (trace)			printf("%s:\n", *p);		filname = 0;		ap = *p++;		if (*ap != '-') {			load1arg(ap);			continue;		}		for (i=1; ap[i]; i++) switch (ap[i]) {		case 'o':			if (++c >= argc)				error(1, "-o where?");			ofilename = *p++;			ofilfnd++;			continue;		case 'u':		case 'e':			if (++c >= argc)				error(1, "-u or -e: arg missing");			enter(slookup(*p++));			if (ap[i]=='e')				entrypt = lastsym;			continue;		case 'H':			if (++c >= argc)				error(1, "-H: arg missing");			if (tsize!=0)				error(1, "-H: too late, some text already loaded");			hsize = atoi(*p++);			continue;		case 'B':			Bflag++;			continue;		case 'A':			if (++c >= argc)				error(1, "-A: arg missing");			if (Aflag) 				error(1, "-A: only one base file allowed");			Aflag = 1;			nflag = 0;			funding = 1;			load1arg(*p++);			trsize = drsize = tsize = dsize = bsize = 0;			ctrel = cdrel = cbrel = 0;			funding = 0;			addsym = nextsym;			continue;		case 'D':			if (++c >= argc)				error(1, "-D: arg missing");			num = htoi(*p++);			if (dsize > num)				error(1, "-D: too small");			dsize = num;			continue;		case 'T':			if (++c >= argc)				error(1, "-T: arg missing");			if (tsize!=0)				error(1, "-T: too late, some text already loaded");			textbase = htoi(*p++);			continue;		case 'l':			save = ap[--i]; 			ap[i]='-';			load1arg(&ap[i]); 			ap[i]=save;			goto next;		case 'M':			Mflag++;			continue;

⌨️ 快捷键说明

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