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

📄 rtld.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * This source code is a product of Sun Microsystems, Inc. and is provided * for unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part.  Users * may copy or modify this source code without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * THIS PROGRAM CONTAINS SOURCE CODE COPYRIGHTED BY SUN MICROSYSTEMS, INC. * SUN MICROSYSTEMS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABLITY * OF SUCH SOURCE CODE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT * EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  SUN MICROSYSTEMS, INC. DISCLAIMS * ALL WARRANTIES WITH REGARD TO SUCH SOURCE CODE, INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN * NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM USE OF SUCH SOURCE CODE, REGARDLESS OF THE THEORY OF LIABILITY. *  * This source code is provided with no support and without any obligation on * the part of Sun Microsystems, Inc. to assist in its use, correction,  * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS * SOURCE CODE OR ANY PART THEREOF. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 *//* @(#)rtld.c 1.60 91/04/02 SMI *//* * Run-time link editor. *//* * Copyright (c) 1989, 1990, 1991 by Sun Microsystems, Inc. */#include <sys/param.h>#include <sys/file.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/mman.h>#include <sys/errno.h>#include <a.out.h>#include <link.h>#include "dynamic.h"#include "reloc_info.h"#include "rtld.h"#include <strings.h>#include "cache.h"#include <sysexits.h>#define VERSION2 2/* * Code collapsing macros. */#define JMPOFF(x)	(x)->v2->ld_plt#define RELOCOFF(x)	(x)->v2->ld_rel#define HASHOFF(x)	(x)->v2->ld_hash#define SYMOFF(x)	(x)->v2->ld_stab#define STROFF(x) 	(x)->v2->ld_symbols#define DONTAPPEND 0#define APPEND 1#if	TARGET==SUN4#               define  MASK(n) ((1<<(n))-1)#               define  IN_RANGE(v,n)   ((-(1<<((n)-1))) <=(v) && (v) < (1<<((n)-1)))#define isitpcrel(rp) (rp->r_type == RELOC_DISP8 || rp->r_type == RELOC_DISP16\	    || rp->r_type == RELOC_DISP32 || rp->r_type == RELOC_WDISP30 \	    || rp->r_type == RELOC_WDISP22)#endif/* * What we do: *	- crt0 will pass in the pointer to dynamic structure of main prog. *	- relocate ourselves. *	- version checking: get the libraries,  *		check the version and mmap them in. *	- relocate the _GOT_ for both user and shared libraries. *	- relocate _PLT_ to the binder. *	- go back to crt0. *//* * Interface between crt0 & ld.so. */struct crt_i1 {	int	crt_baseaddr;		/* Address ld.so is at */	int	crt_dzfd;		/* /dev/zero file descriptor */	int	crt_rlfd;		/* ld.so file descriptor */	struct	link_dynamic *crt_udp;	/* "main_" dynamic */	char	**crt_ep;		/* environment strings */	caddr_t	crt_breakp;		/* place to put initial breakpoint */};/* * Global declarations. */int	devzero_fd;			/* cache for file descriptor */struct	rtc_symb *rtcp;			/* allocated commons */struct	link_map *hlmp = NULL;		/* head of link_map chain */struct	link_map *plmp = NULL;		/* first public link_map */struct	link_map *mlmp;			/* link map for "main" */struct	link_map *ld_lmp;		/* link map for runtime linker */struct	link_object ld_lo;		/* dummy link object for linker */struct	link_map **plmpp;		/* insertion point for new lm's */struct	link_map *flmp = NULL;		/* head of link_map free chain */struct	dl_object *hdlp = NULL;		/* head of dl_object chain */struct	dl_object **pdlpp;		/* insertion point for new dl's */struct	dl_object *fdlp = NULL;		/* head of dl_object free chain */caddr_t	top_of_stack;			/* top of stack (+1) */char	*dl_error;			/* last dynamic linking error */char	*tracing;			/* tracing or running? */char	*preload;			/* other shared object to preload */char	*profile;			/* activate profiling */char	*symbols_public;		/* show ld.so symbols to debuggers */char	*library_path;			/* alternate path for library search */char	**environ;			/* root of environment strings */char	*main_program;			/* string identifying lmp of "main" */char	*ldso_program;			/* string identifying lmp of "ld.so" */char	*cached_symbol = NULL;		/* last string cached by lookup */int	use_cache = 1;			/* tell lo_lookup ok to use cache */int	version_no;			/* link dynamic version number */caddr_t rtmalloc();static	struct nlist *lookup();static	struct nlist *findsb();static	struct nlist *ldsofindsb();static	struct link_map *have_we_got_it();static	struct link_map *new_lmp();static	struct link_map *map_so();static	void map_error();static	struct dl_object *new_dlp();static	void relocate();static	void upd_reloc();static	struct link_map *pc_to_lmp();static	void free_dlp();static	struct dl_object *dlopen_worker();extern	int errno;extern	void rtbinder();		/* declare the binding function */extern	caddr_t caller();		/* function to return our caller's pc *//* * Option storage. */#ifdef PROFint prof_fd;char *prof_buf;#endif#ifdef WHOAMIchar  *progname;#endif#ifdef HRC_TIMEextern void hrc_init();extern int hrc_time();int ftime;int stime;int etime;int time1;int time2;int time3;int time4;int time5;#endif/* * Dummies for LD_PRELOAD. */static	struct link_dynamic_2 pld_ld2;	/* dummy structure for preloads */static	struct link_dynamic pld_ld = 	/* dummy __DYNAMIC */		{2, (struct ld_debug *)0};/* * Run-time link editor bootstrap entry point.  Called by program requiring * initial link editing at startup (generally, crt0). */rtld(version, iptr, dp)	int version;			/* interface version */	caddr_t iptr;			/* interface passed from program */	register struct link_dynamic *dp; /* ld.so dynamic pointer */{	register struct crt_i1 *ip;	/* crt0 version 1 interface structure */	register int reloc;		/* count of internal relocations */	register			/* scratch relocation entry pointer */	    struct relocation_info *rp;	int i;				/* integer temporaries */	char *bp, *cp;			/* character pointer temporaries */	char *buf;			/* temporary storage pointers */	struct	link_object *lop;	/* work pointer */	struct	link_object **lopp; 	/* preloaded object insertion point */	struct	link_map *lmp;		/* work pointer */	struct	link_map *nlmp;		/* newly allocated link_map */	/*	 * Determine interface format.  A prototype interface once existed	 * that passed an address as the first argument.  We assume this	 * address is greater than the size of a page, and thus use this	 * to test for it.  Eventually, support for this will be deleted.	 */	if (version < PAGSIZ) {	/* version 1 of new interface */		ip =  (struct crt_i1 *) iptr;		if (version != 1)			panic(			    "ld.so: unsupported crt interface version of %d\n",			    version);	} else 		/* old interface */		panic("ld.so: obsolete crt interface\n");	/*	 * ld.so must itself be relocated, take care of this now.	 * We can not refer to global data before this step is	 * complete.  Perform the relocation by stepping over all	 * entries in the relocation table and turn them into	 * absolute addresses.  	 *	 * N.B. We have the assumption here that there are no 	 * symbolic relocations which need to be performed.	 */	(int) dp->v2 += ip->crt_baseaddr;#if	TARGET==SUN4	/*	 * SPARC does not have a divide instruction, but we can not	 * call support routine until we have finished relocating the	 * loader.	 */#define RELOC_SIZE sizeof (struct relocation_info)	reloc = 0;	i = GETRELSZ(dp);	while (i != 0) {		i -= RELOC_SIZE;		reloc++;	}#endif#if 	TARGET==SUN3 || TARGET==SUN2	reloc = GETRELSZ(dp) / sizeof (struct relocation_info);#endif	rp = (struct relocation_info *) (RELOCOFF(dp) + 		(dp->ld_version < VERSION2 ? (int) dp : ip->crt_baseaddr));	for (i = 0; i < reloc; i++) {#if	TARGET==SUN4	        upd_reloc(rp, (long *)(rp->r_address + ip->crt_baseaddr),				ip->crt_baseaddr);#endif#if 	TARGET==SUN3 || TARGET==SUN2		*(long *)(rp->r_address + ip->crt_baseaddr) = 			*(long *)(rp->r_address + ip->crt_baseaddr) + ip->crt_baseaddr;#endif		rp++;	}	/*	 * Relocation is completed.  Update any global data necessary	 * to continue.	 */	environ = ip->crt_ep;	rtgetenv();	devzero_fd = ip->crt_dzfd;	pld_ld.ld_un.ld_2 = &pld_ld2;	/* C bug with initializing unions */	/*	 * Initialize link maps.  Create a link map for ld.so -- however	 * do not put it on the "public list" unless we are making its	 * symbols available to the debugger.	 */	pdlpp = &hdlp;	plmpp = &hlmp;	ldso_program = "/usr/lib/ld.so";	ld_lo.lo_name = (long)ldso_program - ip->crt_baseaddr;	ld_lmp = new_lmp(ldso_program, &ld_lo, ip->crt_baseaddr, 	    ip->crt_baseaddr, dp, findsb);	if (!symbols_public)		hlmp = NULL;	plmpp = &hlmp;	db_malloc = heap_malloc = rtmalloc;	is_secure = secure_objects;	main_program = "main_$main_";#ifdef PROF	/*	 * If profiling features are turned on, then see if the profiling	 * file exists.  If so, map in the file and use it as our profile	 * buffer.	 */	if ((prof_fd = open("/tmp/ld.so.profile_buffer", O_RDWR)) != -1) {		if ((prof_buf = mmap(0, 0x2000, PROT_READ | PROT_WRITE, 		    MAP_SHARED, prof_fd, 0)) == (caddr_t)-1)			panic("ld.so: mmap failure (%d) for profile buffer\n",			    errno);		profil(prof_buf, 0x2000, ip->crt_baseaddr, 0x4000);		close(prof_fd);	}#endif PROF#ifdef HRC_TIME	hrc_init();	ftime = stime = hrc_time();#endif	/*	 * Free descriptor on ld.so.	 */	close(ip->crt_rlfd);	/*	 * If we're letting the user freelance, then see if the user has	 * specified any files to be dynamically loaded.  If so, build	 * link-object data structures for them and get them.	 * N.B. THIS IS FOR DEBUGGING ONLY.  IT IS NOT SUPPORTED NOR 	 * IS IT TO BE DOCUMENTED!	 */	if ((cp = preload))		if (!secure_objects()) {			int f = 0;	/* flag for scanning */			lopp = &(struct link_object *)pld_ld2.ld_need;			bp = buf = rtmalloc(strlen(cp) + 1);			do {				*bp = *cp;				if (isspace(*bp) || (*bp == '\0')) {					*bp = '\0';					if (f) {						f = 0;						lop = (struct link_object *)						    rtmalloc(sizeof 						    (struct link_object));						lop->lo_name = (long)buf;						lop->lo_library = 0;						lop->lo_next = NULL;						*lopp = lop;						lopp = &(struct link_object *)						    lop->lo_next;					}				} else 					if (!f) {						f = 1;						buf = bp;					}				bp++;			} while (*cp++);			/*			 * Have list of objects.  Go add them.			 */			(void) new_lmp("ld_$preload_", NULL, (caddr_t)0,			    NULL, &pld_ld, findsb);		}	/*	 * Insert link_map for "main".	 */	mlmp = new_lmp(main_program, NULL, MAIN_BASE, (caddr_t)0, ip->crt_udp,	    findsb);#ifdef HRC_TIME	etime = hrc_time();	time1 = etime - stime;	stime = etime;#endif	/*	 * Walk map of loaded objects, loading their requisite objects as	 * necessary.  Note that the first one we load in this loop is the	 * first one we hand back to the debugger (see use of plmp).	 */	for (lmp = hlmp; lmp; lmp = lmp->lm_next)		if (lmp->lm_ld) {			for (lop = (struct link_object *)				&TEXTBASE(lmp)[lmp->lm_ld->v2->ld_need]; 			    lop != (struct link_object *)&TEXTBASE(lmp)[0];			    lop = (struct link_object *)				      &TEXTBASE(lmp)[lop->lo_next])				if (!have_we_got_it(lop, TEXTBASE(lmp)))					if (nlmp = map_so(lmp, lop))						if (!plmp)							plmp = nlmp;		}		/*	 * If we've just been asked to describe what we would load,	 * describe what we did load, and terminate the process.	 */	if (tracing) {		for (lmp = plmp; lmp; lmp = lmp->lm_next)			if (lmp->lm_lop->lo_library)				printf("\t-l%s.%d => %s\n",				    &lmp->lm_lob[lmp->lm_lop->lo_name],				    lmp->lm_lop->lo_major, 				    lmp->lm_name ? lmp->lm_name : 					"not found");			else				printf("\t%s%s\n", 				    &lmp->lm_lob[lmp->lm_lop->lo_name], 				    lmp->lm_name ? "" : " (not found)");		_exit(0);	}#ifdef HRC_TIME	etime = hrc_time();	time2 = etime - stime;	stime = etime;	/* +++ time in mmap loop */#endif	/* 	 * Relocate all loaded objects.	 */	for (lmp = hlmp; lmp; lmp = lmp->lm_next)		if (lmp != ld_lmp)			relocate(lmp, mlmp);#ifdef HRC_TIME	etime = hrc_time();	time3 = etime - stime;	stime = etime;	/* +++ time in relocate loop */#endif	/*	 * Store in the "main" link_dynamic the list of objects we	 * loaded.  Also return any commons that were allocated.	 */	ip->crt_udp->v2->ld_loaded = plmp;	if (rtcp)		ip->crt_udp->ldd->ldd_cp = rtcp;	/*	 * If we're running under a debugger, let it know we've	 * done our loader thing.	 */	if (ip->crt_udp->ldd->ldd_in_debugger) {		ip->crt_udp->ldd->ldd_bp_addr = ip->crt_breakp;		if (!mlmp->lm_rwt)			if (mprotect(PAGEMASK & 			    (int)ip->crt_breakp, PAGESIZE, 			    PROT_READ | PROT_WRITE | PROT_EXEC) == -1)				map_error("text write-enable", "main");		ip->crt_udp->ldd->ldd_sym_loaded = 1;		ip->crt_udp->ldd->ldd_bp_inst = *(int *)(ip->crt_breakp);#if	TARGET==SUN4		*(long *)(ip->crt_breakp) = TRAP;#endif#if 	TARGET==SUN3 || TARGET==SUN2		*(short *)(ip->crt_breakp) = TRAP;#endif		if (!mlmp->lm_rwt)			if (mprotect(PAGEMASK & 			    (int)ip->crt_breakp, PAGESIZE,			    PROT_READ | PROT_EXEC) == -1)				panic(			    "ld.so: error %d on main text write-protect\n",				    errno);	}	/*	 * Turn write-protect back on for text segments.	 */	for (lmp = hlmp; lmp; lmp = lmp->lm_next) 		if (lmp->lm_rwt) {			if (mprotect(TEXTBASE(lmp), 

⌨️ 快捷键说明

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