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

📄 eshlibld.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 5 页
字号:
					}			}			/* Enter it in the hash table.  Since this is			   done in order of linked-in objects, we don't			   have to mind about weak symbols other than			   ignoring multiple definitions. */			if (SYM_IS_GLOBAL(symp->symtyperaw)			    && SYM_IS_KNOWN(symp->symtyperaw)) {				unsigned long hash					= calc_hash(strings + symp->index);#if 0				if (slist->flags & SYML_IS_SHLIB)					printk("Adding %s in %s to hashtable\n",					       strings + symp->index,					       slist->name);#endif				if (penv->hashtable[hash].slist == NULL) {					D_(printk("Pre-entering #%lu for"						  " %s in %s\n", hash,						  strings + symp->index,						  slist->name));					penv->hashtable[hash].slist = slist;					penv->hashtable[hash].sym = symp;				} else {					D_(printk("EXT Pre-entering #%lu for"						  " %s in %s\n", hash,						  strings + symp->index,						  slist->name));					if (hash_add_extended(penv->hashtable							      + hash,							      slist,							      symp, penv)					    == 0)						return 0;				}			}		}	}	return 1;}/* Read just enough of an armap (a libXXX.a file) to get the basic facts,   like its size and the "extended" names for objects with names longer   than 15 bytes.   Note that lots of the archive-reading functionality depends on   a more restricted file syntax than what binutils accepts, and   so *may* break where binutils does not break.  But as we   check what binutils *outputs*, this should be as safe as   needed. */static int			/* inline hurts here - 2.7.2 */read_armap(int fd, struct armap **mapp){	struct ar_header ar_entry;	struct armap *map;	int next_ar_header_offset		= sizeof ar_entry + sizeof(arfile_magic) - 1;	/* We just read the first two entries; the first (ignored)	   *should* be a "__.SYMDEF" containing offsets to object files	   corresponding to global symbols.  The second is *often*	   "ARFILENAMES/", with a bunch of file names that are > 15	   characters. */	/* Check the magic at file begin, if ok, then read first entry. */	if (sym_lseek(fd, 0, 0) != 0	    || sym_read(fd, (char *) &ar_entry,			sizeof(arfile_magic) - 1) != sizeof(arfile_magic) - 1	    || strncmp(ar_entry.ar_name,		       arfile_magic, sizeof(arfile_magic) - 1) != 0	    || (sym_read(fd, (char *) &ar_entry, sizeof ar_entry)		!= sizeof ar_entry)) {		DB(printk("Bad read or armagic for %d at %d", fd, __LINE__));		return 0;	}	if (strncmp(ar_entry.ar_name,		    arfilenames, sizeof (arfilenames) - 1) != 0) {		next_ar_header_offset			+= simple_strtoul(ar_entry.ar_size, NULL, 10);		/* Pad to even addresses. */		next_ar_header_offset += (next_ar_header_offset % 2);		if ((sym_lseek(fd, next_ar_header_offset, 0)		     != next_ar_header_offset)		    || (sym_read(fd, (char *) &ar_entry, sizeof ar_entry)			!= sizeof ar_entry)) {			DB(printk("Bad read for extended #%d for %d at %d",				  next_ar_header_offset, fd, __LINE__));			return 0;		}	}	if (strncmp(ar_entry.ar_name,		    arfilenames, sizeof (arfilenames) - 1) != 0) {		/* No extended files. */		map = sym_malloc(sizeof (struct armap), "Armap");		if (map == NULL)			return 0;		map->extnames = NULL;		map->extsize = 0;		/* The first ar_header for an object is what we just read. */		map->firstobj = next_ar_header_offset;	} else {		int names_len = simple_strtoul(ar_entry.ar_size, NULL, 10);		char *aname;		map = sym_malloc(sizeof (struct armap) + names_len,				 "Ext armap");		if (map == NULL)			return 0;		map->extnames = (char *) (map + 1);		map->extsize = names_len;		if (sym_read(fd, map->extnames, names_len) != names_len) {			DB(printk("Failed to read extnames in armap for %d",				  fd));			sym_free(map, "No extnames");			return 0;		}		/* Terminate the chunk of names. */		map->extnames[names_len - 1] = 0;		/* Null-terminate each name for easier strcmp-handling.		   Not strictly necessary, but this code is not speed		   priority, and strcmp is easier to keep right than		   strncmp plus length checks. */		for (aname = map->extnames;		     aname < map->extnames + names_len;		     /* nothing */) {			/* The names are \n-terminated in the "extended"			   name entry (why should it be simple?) */			aname = strchr(aname, '\012');			if (aname == NULL)				break;			/* Zero out the \n, so we can strcmp. */			*aname++ = 0;		}		/* The first ar_header for an object is the next one.  We		   know the offset of what we read, so adjust it, and don't		   forget the padding to an even offset. */		map->firstobj			= next_ar_header_offset + sizeof(struct ar_header)			+ names_len + (names_len % 2);	}	map->libsize = sym_lseek(fd, 0, 2);	*mapp = map;	return 1;}/* Move to the location of the object file inside an armap, and   return that location (as lseek SEEK_SET would), or -1 if not found or   other error. */static intseek_obj_armap(int fd, struct armap *map, const char *objname){	struct ar_header ar_entry;	int ar_offset;	int name_len = strlen(objname);	int libsize = map->libsize;	/* We do a linear search through the archive here.	   We could of course save information on the offsets of each object	   file, but that would only be beneficial if it is considered an	   important feature to optimize execution-speed (dlink-speed)	   of programs that are not re-linked when a new library is	   installed. */	/* Search for the right object-file-name. */	for (ar_offset = map->firstobj;	     ar_offset < libsize;	     ar_offset +=		     simple_strtoul(ar_entry.ar_size, NULL, 10),		     ar_offset += ar_offset % 2) {		if (sym_lseek(fd, ar_offset, 0) != ar_offset		    || sym_read(fd, (char *) &ar_entry,				sizeof ar_entry) != sizeof ar_entry) {			DB(printk("Bad read seeking armap of %s\n",				  objname));			return 0;		}		ar_offset += sizeof ar_entry;		/* Check name match.  Long names are coded as / \d+/,		   where \d+ is the index into extnames. */		if (ar_entry.ar_name[0] == ' '		    && ar_entry.ar_name[1] >= '0'		    && ar_entry.ar_name[1] <= '9') {			int name_index				= simple_strtoul(ar_entry.ar_name + 1,						 NULL, 10);			if (map->extnames && name_index < map->extsize			    && strcmp(map->extnames + name_index,				      objname) == 0)				return ar_offset;		}		else if (strncmp(ar_entry.ar_name,				 objname, name_len) == 0)			return ar_offset;	}	DB(printk("Did not find armap of %s\n",		  objname));	return 0;}/* The getenv function is stolen from ld.so-1.9.9 */static char *ldso_getenv(const char *symbol, char **envp, int envc){	char *pnt;	const char *pnt1;	while (envc-- && (pnt = *envp++)) {		pnt1 = symbol;		while (*pnt && *pnt == *pnt1)			pnt1++, pnt++;		if (!*pnt || *pnt != '=' || *pnt1)			continue;		return pnt+1;	}	return 0;}/*#***************************************************************************#*# FUNCTION NAME: perform_relocations*#*# PARAMETERS	: Information about location and size of .text,*#		  .data and .bss and pointers to relocations,*#		  sizes of .text and .data relocations, symbols and*#		  strings used in the symbols.*#*# RETURNS	: 0 if an error was encountered, 1 on success.*#*# SIDE EFFECTS : Changes the contents of .text and .data*#*# DESCRIPTION	: Worker function for*#		  perform_cris_aout_relocations, does all the relocations.*#*#**************************************************************************/static intperform_relocations(unsigned long text, unsigned long tlength,		    unsigned long data, unsigned long dlength,		    unsigned long bss,#ifdef SANITYCHECK_RELOC		    unsigned long blength,#endif		    unsigned long segstart, unsigned char *relend,		    struct symlist *slist,		    struct progenv *penv){	struct reloctype *rel;	struct reloctype *relstart = slist->relocs;	struct symtype *syms = slist->syms;	unsigned long address, value;#ifdef SANITYCHECK_RELOC	/* Check that the length is a multiple of the reloc-size. */	if (((relend - (unsigned char *) relstart) % 12) != 0	    || (penv && penv->symbase && penv->symbase->symslen % 12) != 0) {		penv->env_flags |= PROG_FATAL_ERROR;		DB(printk("Bad input to perform_relocations\n"));		return 0;	}#endif	/* Stop before the last text-reloc if we're relocating the data	   segment. */	if (segstart == data)		/* A div + (implicit) mul here cannot be optimized away. */		relstart = (struct reloctype *) ((char *) relstart						 + slist->ntrelocs);	/* We go in decreasing order, since we started that way once	   upon a time, and measurements show a (small) loss when trying	   to switch to increasing order. */	for (rel = (struct reloctype *) relend - 1;	     rel >= (struct reloctype *) relstart;	     rel--) {#ifdef SANITYCHECK_RELOC		if (		    /* Basically invalid data in the reloc? */		    ! VALIDSEGSYM(rel->segsym, syms)		    /* Address outside this segment?		       (This check is a bit dirty since we deduce which		       segment segstart actually is, but anything to assert		       sanity here...)		       Note that the address is relative to segstart here. */		    || (segstart == text && rel->address > tlength)		    || (segstart == data && rel->address > dlength)		    /* Note that it does not make sense to compare the		       addend to the segment it is relative to, since it		       may validly point outside it.	An ad-hoc		       assumption is made here, that it does not point		       more than 16M outside the program space. */		    || (long) rel->addend > (long) (0x1000000 + tlength						    + dlength + blength)		    || (long) rel->addend < -0x1000000) {			/* If so, look no further. */			penv->env_flags |= PROG_FATAL_ERROR;			DB(printk("Bad relocs or symbols\n"));			return 0;		}#endif		/* Weak definitions count as undefined, so a later strong		   symbol can override. */		if (IS_UNDEF(rel->segsym, syms)) {			if (syms != NULL			    /* It may be that this is a weak symbol or			       reference that we're already checked with			       the old and same number of objects.  Then			       we will not find anything new when			       searching the symbols. */			    && get_sym(syms + SEGMENT(rel->segsym),				       slist, penv)) {				address = segstart + rel->address;				value = syms[SEGMENT(rel->segsym)].value					+ rel->addend; 			} else {				/* It may also have been that this was a				   weak undefined symbol; then just				   continue; the place is marked for				   revisits.  Else this is a real				   failure. */				if (syms == NULL				    || SYMTYPE(syms[SEGMENT(rel->segsym)]					       .symtyperaw) != WEAK_SYM) {					DB(if (syms != NULL)					   	printk("Bad symtype %ld for %s in %s\n",						       SYMTYPE(syms[SEGMENT(rel->segsym)]							       .symtyperaw),						       syms[SEGMENT(rel->segsym)].index						       + slist->strings,						       slist->name));						       					return 0;				}				address = segstart + rel->address;				value = 0;			}		} else if (IS_RESOLVED(rel->segsym, syms)) {			address = segstart + rel->address;			value = syms[SEGMENT(rel->segsym)].value				+ rel->addend;		} else if (SEGMENT(rel->segsym) == TEXTSEG) {			address = segstart + rel->address;			value = text + rel->addend;		} else if (SEGMENT(rel->segsym) == DATASEG) {			address = segstart + rel->address;			value = data + rel->addend - tlength;		} else if (SEGMENT(rel->segsym) == BSSSEG) {			address = segstart + rel->address;			value = bss + rel->addend - tlength - dlength;		} else if (SEGMENT(rel->segsym) == ABSSEG			   /* See comment at definition of BUGVALUE_ABSSEG. */			   || SEGMENT(rel->segsym) == BUGVALUE_ABSSEG) {			address = segstart + rel->address;			value = rel->addend;		} else {			penv->env_flags |= PROG_FATAL_ERROR;			DB(printk("Bad reloc segment %lu\n",				  rel->segsym));			return 0;		}		D_(printk("W 0x%lx to 0x%lx\n", value, address));		writedw(address, value);	}	/* This was a success. */	return 1;}#if SHARE_LIB_CORE/* These functions are not used when not sharing loaded libraries   whatsoever. *//* Free this shared object and maybe its base library, and possibly the   objects this object depends on. */static voidshlibobj_free(struct shlib_obj **objpp){	/* TODO: It'd be nice to let it linger and let kerneld reap it,	   just as with kernel modules. */	struct shlib_obj *obj = *objpp;	struct shlib_obj **nextobjpp;	struct shliblist **nextshlibpp;	DB(int i = 0;)	D_(printk("Will reap %s in %s\n", obj->common.name,		  obj->base_lib->common.name));	/* We need to find the "link" to change, so we can free it and	   unlink this object.  This means a linear search through all	   libraries, then all objects of that library.  This is O(N+M),	   since the lists are not double-linked (although there is a

⌨️ 快捷键说明

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