Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3fd6805f authored by Sam Ravnborg's avatar Sam Ravnborg Committed by Greg Kroah-Hartman
Browse files

[PATCH] Clean up module.c symbol searching logic

parent 58383af6
Loading
Loading
Loading
Loading
+41 −32
Original line number Diff line number Diff line
@@ -135,6 +135,18 @@ extern const unsigned long __start___kcrctab_gpl[];
#define symversion(base, idx) ((base) ? ((base) + (idx)) : NULL)
#endif

/* lookup symbol in given range of kernel_symbols */
static const struct kernel_symbol *lookup_symbol(const char *name,
	const struct kernel_symbol *start,
	const struct kernel_symbol *stop)
{
	const struct kernel_symbol *ks = start;
	for (; ks < stop; ks++)
		if (strcmp(ks->name, name) == 0)
			return ks;
	return NULL;
}

/* Find a symbol, return value, crc and module which owns it */
static unsigned long __find_symbol(const char *name,
				   struct module **owner,
@@ -142,39 +154,41 @@ static unsigned long __find_symbol(const char *name,
				   int gplok)
{
	struct module *mod;
	unsigned int i;
	const struct kernel_symbol *ks;

	/* Core kernel first. */ 
	*owner = NULL;
	for (i = 0; __start___ksymtab+i < __stop___ksymtab; i++) {
		if (strcmp(__start___ksymtab[i].name, name) == 0) {
			*crc = symversion(__start___kcrctab, i);
			return __start___ksymtab[i].value;
		}
	ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);
	if (ks) {
		*crc = symversion(__start___kcrctab, (ks - __start___ksymtab));
		return ks->value;
	}
	if (gplok) {
		for (i = 0; __start___ksymtab_gpl+i<__stop___ksymtab_gpl; i++)
			if (strcmp(__start___ksymtab_gpl[i].name, name) == 0) {
				*crc = symversion(__start___kcrctab_gpl, i);
				return __start___ksymtab_gpl[i].value;
		ks = lookup_symbol(name, __start___ksymtab_gpl,
					 __stop___ksymtab_gpl);
		if (ks) {
			*crc = symversion(__start___kcrctab_gpl,
					  (ks - __start___ksymtab_gpl));
			return ks->value;
		}
	}

	/* Now try modules. */ 
	list_for_each_entry(mod, &modules, list) {
		*owner = mod;
		for (i = 0; i < mod->num_syms; i++)
			if (strcmp(mod->syms[i].name, name) == 0) {
				*crc = symversion(mod->crcs, i);
				return mod->syms[i].value;
		ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms);
		if (ks) {
			*crc = symversion(mod->crcs, (ks - mod->syms));
			return ks->value;
		}

		if (gplok) {
			for (i = 0; i < mod->num_gpl_syms; i++) {
				if (strcmp(mod->gpl_syms[i].name, name) == 0) {
					*crc = symversion(mod->gpl_crcs, i);
					return mod->gpl_syms[i].value;
				}
			ks = lookup_symbol(name, mod->gpl_syms,
					   mod->gpl_syms + mod->num_gpl_syms);
			if (ks) {
				*crc = symversion(mod->gpl_crcs,
						  (ks - mod->gpl_syms));
				return ks->value;
			}
		}
	}
@@ -1444,17 +1458,12 @@ static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
#ifdef CONFIG_KALLSYMS
int is_exported(const char *name, const struct module *mod)
{
	unsigned int i;

	if (!mod) {
		for (i = 0; __start___ksymtab+i < __stop___ksymtab; i++)
			if (strcmp(__start___ksymtab[i].name, name) == 0)
	if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab))
		return 1;
		return 0;
	}
	for (i = 0; i < mod->num_syms; i++)
		if (strcmp(mod->syms[i].name, name) == 0)
	else
		if (lookup_symbol(name, mod->syms, mod->syms + mod->num_syms))
			return 1;
		else
			return 0;
}