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

📄 rtld.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
			fprintf(stderr, "word displacement overflow at %#x",				 rp->r_address);		*(short *)where = what;		break;	case RELOC_22:	case RELOC_BASE22:		what += *where & MASK(22);		if (!IN_RANGE(what,22))			fprintf(stderr, "sethi displacement overflow at %#x",				 rp->r_address);		*(long *)where = (*(long *)where & ~MASK(22)) | (what & MASK(22));		break;	case RELOC_HI22:		what += (*where<<32-22) & MASK(22);		*(long *)where = (*(long *)where & ~MASK(22)) 			| ((what>>(32-22)) & MASK(22));		break;	case RELOC_WDISP22:		what += *where & MASK(22);		if (what & MASK(2) )			fprintf(stderr, "odd word displacement at %#x",				 rp->r_address);		what >>= 2;		if (!IN_RANGE(what,22))			fprintf(stderr, "branch displacement overflow at %#x",				 rp->r_address);		*(long *)where = (*(long *)where & ~MASK(22)) | (what & MASK(22));		break;			case RELOC_WDISP30:		what += *where & MASK(30);		if (what & MASK(2) )			fprintf(stderr, "odd word displacement at %#x",				 rp->r_address);		what >>= 2;		*(long *)where = (*(long *)where & ~MASK(30)) | (what&MASK(30));		break;	case RELOC_32:	case RELOC_GLOB_DAT:	case RELOC_DISP32:		what += *where;		*(long *)where = what;		break;	default:		fprintf(stderr, "unknown relocation type %d", rp->r_type);		break;	}#endif #if 	TARGET==SUN3 || TARGET==SUN2	/*	 * Put the value back in the segment,	 * while checking for overflow.	 */	what += *where;	*(long *)where = what;	/* ++++ need to add this	switch (rp->r_length) {	case 0:			if (what < -128 || what > 127)			fprintf(stderr, "byte displacement overflow at %#x",				 rp->r_address);		*where = what;		break;	case 1:		if (what < -32768 || what > 32767)			fprintf(stderr, "word displacement overflow at %#x",				 rp->r_address);		*(short *)where = what;		break;	case 2:				*(long *)where = what;		break;	}	*/#endif}/* * Calculate hash value for symbol being looked up. */static intgethashv(sn)	char *sn;{	int val;			/* accumulator for hash value */	/*	 * Calculate hash value for symbol being looked up.	 */	for (val = 0; *sn;)		val = (val<<1) + *sn++;	return(val);}static struct nlist *ldsofindsb(lmp, sn, clmp)	struct link_map *lmp;	char *sn;	struct link_map *clmp;{	struct nlist *sp;	if ((sp = findsb(lmp, sn, clmp)) == 0)		return (0);	if ((sp->n_value == 0) || (sp->n_type == N_EXT+N_UNDF))		return (0);	LM2LP(lmp)->lp_symbol_base = ld_lmp->lm_addr;	return (findsb(ld_lmp, sn, clmp));}#define HASHMASK 0x7fffffffstatic struct nlist *findsb(lmp, sn, clmp)	struct link_map *lmp;	char *sn;	struct link_map *clmp;{	register char *cp;		/* temporary */	register char *s1;		/* string handling pointers */	struct fshash *p;		/* working pointer to .so symbols */	int i;				/* temporary */	struct nlist *sp;		/* symbol entry pointer */	static int hashval;		/* cache hash value of last symbol */	static char *lp;		/* cache last symbol pointer */	/* 	 * this is a questionable cache since the same pointer may	 * pointed to a different symbol. ++++	 */	if (lp != sn)		hashval = gethashv(sn);	if (LM2LP(lmp)->lp_hash == (struct fshash *)&lmp->lm_addr[0])		return(0); 	/* not found */	i = (hashval & HASHMASK) % (lmp->lm_ld->v2->ld_buckets == 0 	    ? RTHS : lmp->lm_ld->v2->ld_buckets);	p = LM2LP(lmp)->lp_hash + i; 	if (p->fssymbno != -1)		do {			sp = &LM2LP(lmp)->lp_symtab[p->fssymbno];			s1 = sn;			cp = &LM2LP(lmp)->lp_symstr[sp->n_un.n_strx];			while (*s1 == *cp++)				if (*s1++=='\0') {					return(sp);	/* found */				}			if (p->next == 0) 				return(0);		/* not found */			else 				continue;		/* next symbol */		} while (p = &LM2LP(lmp)->lp_hash[p->next]);	return(0);}/* * Lookup symbol with name (s).  Return pointer to symbol table entry * representing it as well as index to dynamic object which defines it. */staticstruct nlist *lookup(s, lmpp, clmp)	char *s;	struct link_map **lmpp;	struct link_map *clmp;{	register struct link_map *lmp;	/* working pointer */	register char *cp;		/* string handling pointers */	register char *s1;		/* string handling pointers */	struct nlist *sp;		/* symbol table entry */	struct nlist *savesp;		/* save common data symbol entry */	int msize = 0;			/* common maximum size */	struct rtc_symb *rs;		/* new common */	struct rtc_symb *trs;		/* temporary for new common */	static struct nlist *lsp;	/* cached copy of last symbol found */	static struct link_map *lmpc;	/* cached link map pointer */	/*	 * Heuristic: if this symbol is the same as the last one, then	 * just skip all this work.	 * XXX should count this to see how effective it is.	 */	if (cached_symbol)		if (!strcmp(cached_symbol, s)) {			*lmpp = lmpc;			return(lsp);		}	cached_symbol = s;	/*	 * Over all loaded objects, determine find the hash entry corresponding	 * to this value, and search for a definition for this symbol.	 */	for (lmp = hlmp; lmp; lmp = lmp->lm_next) {		lmpc = lmp;		if (lsp = sp = (*(LM2LP(lmp)->lp_interp))(lmp, s, clmp)) {			/*			 * We found a match.  If it is simply a reference 			 * and not a definition we proceed to the next object.			 * If it is a definition, and not a common then we 			 * have found what we're looking for so return it. 			 * Otherwise, determine whether the common has already 			 * been allocated, and if so, return that pointer.			 */			if (sp->n_value == 0)				continue;			if (sp->n_type != N_EXT+N_UNDF) {				if (msize == 0) {					*lmpp = lmp;					return (sp);				}			} else {				/* 				 * look up the runtime allocated commom				 * symbol table 				 */				savesp = sp;				trs = rtcp;				while (trs) {					s1 = s;					cp = trs->rtc_sp->n_un.n_name;					while (*s1 == *cp++)						if (*s1++=='\0')						    return (lsp = trs->rtc_sp);					trs = trs->rtc_next;				}				/*				 * It's an unallocated common, 				 * accumulate size information.				 */				if (msize < sp->n_value)					msize = sp->n_value;				continue;			}		}	}	/*	 * If we got this far, we either have found nothing suitable or	 * else have a common.  In the former, punt, otherwise we now	 * know enough to allocate the common so do so.	 */	if (msize == 0) {		return (0);	} else {		rs = (struct rtc_symb *) rtmalloc(sizeof (struct rtc_symb));		rs->rtc_sp = (struct nlist *)rtmalloc(sizeof (struct nlist));		trs = rtcp;		rtcp = rs;		rs->rtc_next = trs;		*(rs->rtc_sp) = *savesp;		rs->rtc_sp->n_un.n_name = rtmalloc(strlen(s) + 1);		strcpy(rs->rtc_sp->n_un.n_name, s);		rs->rtc_sp->n_type = N_COMM;		rs->rtc_sp->n_value = (long)rtmalloc(msize);		*lmpp = lmpc = hlmp;		return (lsp = rs->rtc_sp);	}}/* * Procedure call binding.  Called on initial call reference to a global * unbound symbol.   */intbinder(pc, relocindex)	caddr_t pc;	int relocindex;{	int address;			/* target address */	register struct link_map *lmp;	/* link_map describing calling obj */	register struct 		/* working relocation pointer */	    relocation_info *rp;	register struct nlist *sp;	/* entry for symbol being referenced */	register char *symbol;		/* symbol being searched for */	struct link_map *llmp;		/* link_map in which symbol is found */	/*	 * Find the object that our caller came from.	 */	for (lmp = hlmp; lmp; lmp = lmp->lm_next)		if (pc > (caddr_t)(LM2LP(lmp)->lp_plt) && 		    pc < (caddr_t)((int)LM2LP(lmp)->lp_plt + 			lmp->lm_ld->v2->ld_plt_sz))			goto gotit;	/*	 * If no object can be found, we can't understand how we got	 * here, so we panic.	 */	if (lmp == NULL)		panic("ld.so: unidentifiable procedure reference at 0x%x\n", 		    pc);gotit:	/*	 * Need to know which link_dynamic version for plt handling.	 * This interface will be revised post 4.0 ++++++	 */#if	TARGET==SUN4#define	LAST22BITS	0x3fffff	version_no = lmp->lm_ld->ld_version;	if (version_no == 3)		relocindex = *(int *)(pc + 4) & LAST22BITS;#endif	/*	 * Find the symbol being referenced, and then find a definition for it.	 * If the latter can not be found, then terminate the program.	 */	/*	 * N.B. Different error handling possibilities are a CASE	 * opportunity: namely, incremental program construction and	 * calls to debuggers.	 */	rp = &LM2LP(lmp)->lp_rp[relocindex];	sp = &LM2LP(lmp)->lp_symtab[rp->r_symbolnum];	symbol = &LM2LP(lmp)->lp_symstr[sp->n_un.n_strx];	if ((sp = lookup(symbol, &llmp, lmp)) == NULL)		panic("ld.so: call to undefined procedure %s from 0x%x\n",		    symbol, pc);	/*	 * Rebuild the relocation entry to direct future calls directly	 * to the target procedure.  Return the address to which this call	 * should ultimately return.	 */	/*	 * N.B. Much opportunity here for:	 *	- call graph profiling.	 *	- alternative procedure call implementation (RPC).	 *	- value-added interposing.	 */	address = (int)&LM2LP(llmp)->lp_symbol_base[sp->n_value];	stuffit((long *)&lmp->lm_addr[rp->r_address], address);	return (address);}/* * Rebuild a _PLT_ entry after initial binding.   */stuffit(where, what)	long *where;	int what;{#if	TARGET==SUN4	long *i = where;	switch (version_no) {	case 3:		*i = SETHI;		*i = (*i & ~MASK(22)) | ((what>>(32-22)) & MASK(22));		i++;		*i = JMPI;		*i = (*i & ~MASK(10)) | (what & MASK(10));		break;	default:		*i = SETHI;		*i = (*i & ~MASK(22)) | ((what>>(32-22)) & MASK(22));		i++;		*i = ORIT;		*i = (*i & ~MASK(10)) | (what & MASK(10));		*i++;		*i++ = JMPI;		*i = NOP;		break;	}#endif#if 	TARGET==SUN3 || TARGET==SUN2	char *i = (char *)where;		*where = what;	*(short *)(i - 2) = JUMP;#endif}/* * Utility function to round "v" to the next "r" boundary. */round(v, r)	u_int v;	u_int r;{	r--;	v += r;	v &= ~(long)r;	return (v);}/* * Make sure we have a source of heap. */staticget_zero_object(){	int zfd;	if (devzero_fd == -1)		devzero_fd = open("/dev/zero", O_RDONLY);	return (devzero_fd != -1);}/* * Local heap allocator.  Very simple, does not support storage freeing. * XXX Should be upgraded to support multiple heaps.  Should also handle * /dev/zero allocation errors. */caddr_trtmalloc(nb)	int nb;{	static caddr_t cp = 0;	static caddr_t sp = 0;	caddr_t tp;	struct rlimit rlimit;	int sl;	if (cp == 0) {		getrlimit(RLIMIT_STACK, &rlimit);		sl = rlimit.rlim_cur - (rlimit.rlim_cur % PAGSIZ);		sp = cp = (caddr_t)(top_of_stack - sl);	} 	if (cp + round(nb, (long)sizeof (double)) >= sp) {		if (!get_zero_object())			map_error("map heap", "/dev/zero");		if ((sp = mmap(sp, round(nb, PAGSIZ), PROT_READ | PROT_WRITE,		    MAP_FIXED | MAP_PRIVATE, devzero_fd, 0)) == (caddr_t)-1)			    map_error("map heap", "/dev/zero");		sp += round(nb,PAGSIZ);	}	tp = cp;	cp += round(nb, sizeof (double));	return (tp);} /* * Run-time link editor private getenv system call.  Scans for our  * special strings, and also calculates top of stack. */char	ld_library_path[] =	"LD_LIBRARY_PATH";char	ld_trace[] =		"LD_TRACE_LOADED_OBJECTS";char	ld_profile[] =		"LD_PROFILE";char	ld_preload[] =		"LD_PRELOAD";char	ld_symbols_public[]=	"LD_SYMBOLS_PUBLIC";staticrtgetenv(){	register char **p = environ;	register char *v;	/*	 * Guard against no environment.  This seems practically impossible,	 * as the variable "environ" is initialized in crt0 with an address	 * on the stack.  However, if it actually does happen, we need to	 * fake out the top of user_stack.	 */	if ((p == NULL) || (*p == NULL)) {		top_of_stack = (caddr_t)(((int)&p + PAGSIZ - 1) 		    & ~(PAGSIZ - 1));		return;	}	/*	 * Scan for LD_ environment variables that affect our behavior.	 */	while (v = *p++) {		if (strncmp(v, "LD_", 3)) 			continue;		if (!strncmp(v, ld_library_path, sizeof (ld_library_path) - 1))			library_path = v + sizeof (ld_library_path);

⌨️ 快捷键说明

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