예제 #1
0
static const char *get_modinfo_value(struct obj_file *f, const char *key)
{
	struct obj_section *sec;
	char *p, *v, *n, *ep;
	size_t klen = strlen(key);

	if (strcmp(key, "filename") == 0) {
		return(f->filename);
	}

	sec = obj_find_section(f, ".modinfo");
	if (sec == NULL)
		return NULL;

	p = sec->contents;
	ep = p + sec->header.sh_size;
	while (p < ep) {
		v = strchr(p, '=');
		n = strchr(p, '\0');
		if (v) {
			if (v - p == klen && strncmp(p, key, klen) == 0)
				return v + 1;
		} else {
			if (n - p == klen && strcmp(p, key) == 0)
				return n;
		}
		p = n + 1;
	}

	return NULL;
}
예제 #2
0
/*
 *	Extract any generic string from the given symbol.
 *	Note: assumes same machine and arch for depmod and module.
 */
static void extract_generic_string(struct obj_file *f, MODULE *mod)
{
	struct obj_section *sec;
	char *p, *ep, *s, **latest;

	sec = obj_find_section(f, ".modstring");
	if (sec == NULL)
		return;
	p = sec->contents;
	ep = p + sec->header.sh_size;
	while (p < ep) {
		s = p;
		while (*p != '\0' && p < ep)
			p++;
		if (p >= ep) {
			bb_error_msg("unterminated generic string '%*s'", (int)(p - s), s);
			break;
		}
		if (p++ == s)		/* empty string? */
			continue;
		mod->generic_string = xrealloc(mod->generic_string, ++(mod->n_generic_string)*sizeof(*(mod->generic_string)));
		latest = mod->generic_string + mod->n_generic_string-1;
		*latest = bb_xstrdup(s);
	}
}
예제 #3
0
static void show_module_parameters(struct obj_file *f, const char *format)
{
	struct obj_section *sec;
	char *ptr, *value, *n, *endptr;
	int namelen;

	sec = obj_find_section(f, ".modinfo");
	if (sec == NULL) {
		error("module does not support typed parameters");
		return;
	}
	ptr = sec->contents;
	endptr = ptr + sec->header.sh_size;
	while (ptr < endptr) {
		value = strchr(ptr, '=');
		n = strchr(ptr, '\0');
		if (value) {
			namelen = value - ptr;
			if (namelen >= 5 && strncmp(ptr, "parm_", 5) == 0
			    && !(namelen > 10 && strncmp(ptr, "parm_desc_", 10) == 0)) {
				char *pname = xmalloc(namelen + 1);
				char *desckey = xmalloc(namelen + 5 + 1);

				strncpy(pname, ptr + 5, namelen - 5);
				pname[namelen - 5] = '\0';

				strcpy(desckey, "parm_desc_");	/* safe, xmalloc */
				strncat(desckey, ptr + 5, namelen - 5);
				desckey[namelen + 5] = '\0';

				format_query_line(f, format, pname, value + 1, get_modinfo_value(f, desckey));

				free(pname);
				free(desckey);
			}
		} else {
			if (n - ptr >= 5 && strncmp(ptr, "parm_", 5) == 0) {
				error("parameter %s found with no value", ptr);
			}
		}
		ptr = n + 1;
	}
}
예제 #4
0
/*
 *	Read the symbols in an object and register them in the symbol table.
 *	Return -1 if there is an error.
 */
static int loadobj(const char *objname, int ignore_suffix)
{
	static char *currdir;
	static int currdir_len;
	int fp;
	MODULE *mod;
	SYMBOL *undefs[5000];
	SYMBOL *defsym[5000];
	struct obj_file *f;
	struct obj_section *sect;
	struct obj_symbol *objsym;
	int i;
	int is_2_2;
	int ksymtab;
	int len;
	int n_undefs = 0;
	int n_defsym = 0;
	char *p;
	void *image;
	unsigned long m_size;

	p = strrchr(objname, '/');
	len = 1 + (int)(p - objname);

	if ((fp = open(objname, O_RDONLY)) < 0)
		return 1;

	if (!(f = obj_load(fp, ET_REL, objname))) {
		close(fp);
		return -1;
	}
	close(fp);

	/*
	 * Allow arch code to define _GLOBAL_OFFSET_TABLE_
	 */
	arch_create_got(f);

	/*
	 * If we have changed base directory
	 * then use the defined symbols from modules
	 * in the _same_ directory to resolve whatever
	 * undefined symbols there are.
	 *
	 * This strategy ensures that we will have
	 * as correct dependencies as possible,
	 * even if the same symbol is defined by
	 * other modules in other directories.
	 */
	if (currdir_len != len || currdir == NULL ||
	    strncmp(currdir, objname, len) != 0) {
		if (currdir)
			resolve();
		currdir = bb_xstrdup(objname);
		currdir_len = len;
	}

	mod = modules + n_modules++;
	mod->name = bb_xstrdup(objname);

	if ((sect = obj_find_section(f, "__ksymtab")) != NULL)
		ksymtab = sect->idx; /* Only in 2.2 (or at least not 2.0) */
	else
		ksymtab = -1;

	if (sect ||
	    obj_find_section(f, ".modinfo") ||
	    obj_find_symbol(f, "__this_module"))
		is_2_2 = 1;
	else
		is_2_2 = 0;

	for (i = 0; i < HASH_BUCKETS; ++i) {
		for (objsym = f->symtab[i]; objsym; objsym = objsym->next) {
			if (objsym->secidx == SHN_UNDEF) {
				if (ELFW(ST_BIND)(objsym->info) != STB_WEAK &&
				    objsym->r_type /* assumes that R_arch_NONE is always 0 on all arch */) {
					undefs[n_undefs++] = addsym(objsym->name,
								    mod,
								    SYM_UNDEF,
								    ignore_suffix);
				}
				continue;
			}
			/* else */

			if (is_2_2 && ksymtab != -1) {
				/* A 2.2 module using EXPORT_SYMBOL */
				if (objsym->secidx == ksymtab &&
				    ELFW(ST_BIND)(objsym->info) == STB_GLOBAL) {
					/* Ignore leading "__ksymtab_" */
					defsym[n_defsym++] = addsym(objsym->name + 10,
								    mod,
								    SYM_DEFINED,
								    ignore_suffix);
				}
				continue;
			}
			/* else */

			if (is_2_2) {
				/*
				 * A 2.2 module _not_ using EXPORT_SYMBOL
				 * It might still want to export symbols,
				 * although strictly speaking it shouldn't...
				 * (Seen in pcmcia)
				 */
				if (ELFW(ST_BIND)(objsym->info) == STB_GLOBAL) {
					defsym[n_defsym++] = addsym(objsym->name,
								    mod,
								    SYM_DEFINED,
								    ignore_suffix);
				}
				continue;
			}
			/* else */

			/* Not undefined or 2.2 ksymtab entry */
			if (objsym->secidx < SHN_LORESERVE
			/*
			 * The test below is removed for 2.0 compatibility
			 * since some 2.0-modules (correctly) hide the
			 * symbols it exports via register_symtab()
			 */
			/* && ELFW(ST_BIND)(objsym->info) == STB_GLOBAL */
			     ) {
				defsym[n_defsym++] = addsym(objsym->name,
							    mod,
							    SYM_DEFINED,
							    ignore_suffix);
			}
		}
	}

	/*
	 *	Finalize the information about a module.
	 */
	mod->defsym.n_syms = n_defsym;
	if (n_defsym > 0) {
		int size = n_defsym * sizeof(SYMBOL *);

		mod->defsym.symtab = (SYMBOL **)xmalloc(size);
		memcpy(mod->defsym.symtab, defsym, size);
	} else
		mod->defsym.symtab = NULL;

	mod->undefs.n_syms = n_undefs;
	if (n_undefs > 0) {
		int size = n_undefs * sizeof(SYMBOL *);

		mod->undefs.symtab = (SYMBOL **) xmalloc(size);
		memcpy(mod->undefs.symtab, undefs, size);
		mod->resolved = 0;
	} else {
		mod->undefs.symtab = NULL;
		mod->resolved = 1;
	}

	/* Do a pseudo relocation to base address 0x1000 (arbitrary).
	 * All undefined symbols are treated as absolute 0.  This builds
	 * enough of a module to allow extraction of internal data such
	 * as device tables.
	 */
	obj_clear_undefineds(f);
	obj_allocate_commons(f);
	m_size = obj_load_size(f);
	if (!obj_relocate(f, 0x1000)) {
		bb_error_msg("depmod obj_relocate failed\n");
		return(-1);
	}
	extract_generic_string(f, mod);
	image = xmalloc(m_size);
	obj_create_image(f, image);
	free(image);

	obj_free(f);
	return 0;
}