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

📄 module.c

📁 linux 2.6.19 kernel source code before patching
💻 C
📖 第 1 页 / 共 5 页
字号:
	unsigned int nloaded = 0, i, size[2];	struct module_sect_attrs *sect_attrs;	struct module_sect_attr *sattr;	struct attribute **gattr;		/* Count loaded sections and allocate structures */	for (i = 0; i < nsect; i++)		if (sechdrs[i].sh_flags & SHF_ALLOC)			nloaded++;	size[0] = ALIGN(sizeof(*sect_attrs)			+ nloaded * sizeof(sect_attrs->attrs[0]),			sizeof(sect_attrs->grp.attrs[0]));	size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.attrs[0]);	sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);	if (sect_attrs == NULL)		return;	/* Setup section attributes. */	sect_attrs->grp.name = "sections";	sect_attrs->grp.attrs = (void *)sect_attrs + size[0];	sect_attrs->nsections = 0;	sattr = &sect_attrs->attrs[0];	gattr = &sect_attrs->grp.attrs[0];	for (i = 0; i < nsect; i++) {		if (! (sechdrs[i].sh_flags & SHF_ALLOC))			continue;		sattr->address = sechdrs[i].sh_addr;		sattr->name = kstrdup(secstrings + sechdrs[i].sh_name,					GFP_KERNEL);		if (sattr->name == NULL)			goto out;		sect_attrs->nsections++;		sattr->mattr.show = module_sect_show;		sattr->mattr.store = NULL;		sattr->mattr.attr.name = sattr->name;		sattr->mattr.attr.owner = mod;		sattr->mattr.attr.mode = S_IRUGO;		*(gattr++) = &(sattr++)->mattr.attr;	}	*gattr = NULL;	if (sysfs_create_group(&mod->mkobj.kobj, &sect_attrs->grp))		goto out;	mod->sect_attrs = sect_attrs;	return;  out:	free_sect_attrs(sect_attrs);}static void remove_sect_attrs(struct module *mod){	if (mod->sect_attrs) {		sysfs_remove_group(&mod->mkobj.kobj,				   &mod->sect_attrs->grp);		/* We are positive that no one is using any sect attrs		 * at this point.  Deallocate immediately. */		free_sect_attrs(mod->sect_attrs);		mod->sect_attrs = NULL;	}}#elsestatic inline void add_sect_attrs(struct module *mod, unsigned int nsect,		char *sectstrings, Elf_Shdr *sechdrs){}static inline void remove_sect_attrs(struct module *mod){}#endif /* CONFIG_KALLSYMS */#ifdef CONFIG_SYSFSint module_add_modinfo_attrs(struct module *mod){	struct module_attribute *attr;	struct module_attribute *temp_attr;	int error = 0;	int i;	mod->modinfo_attrs = kzalloc((sizeof(struct module_attribute) *					(ARRAY_SIZE(modinfo_attrs) + 1)),					GFP_KERNEL);	if (!mod->modinfo_attrs)		return -ENOMEM;	temp_attr = mod->modinfo_attrs;	for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) {		if (!attr->test ||		    (attr->test && attr->test(mod))) {			memcpy(temp_attr, attr, sizeof(*temp_attr));			temp_attr->attr.owner = mod;			error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);			++temp_attr;		}	}	return error;}void module_remove_modinfo_attrs(struct module *mod){	struct module_attribute *attr;	int i;	for (i = 0; (attr = &mod->modinfo_attrs[i]); i++) {		/* pick a field to test for end of list */		if (!attr->attr.name)			break;		sysfs_remove_file(&mod->mkobj.kobj,&attr->attr);		if (attr->free)			attr->free(mod);	}	kfree(mod->modinfo_attrs);}#endif#ifdef CONFIG_SYSFSint mod_sysfs_init(struct module *mod){	int err;	if (!module_sysfs_initialized) {		printk(KERN_ERR "%s: module sysfs not initialized\n",		       mod->name);		err = -EINVAL;		goto out;	}	memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj));	err = kobject_set_name(&mod->mkobj.kobj, "%s", mod->name);	if (err)		goto out;	kobj_set_kset_s(&mod->mkobj, module_subsys);	mod->mkobj.mod = mod;	kobject_init(&mod->mkobj.kobj);out:	return err;}int mod_sysfs_setup(struct module *mod,			   struct kernel_param *kparam,			   unsigned int num_params){	int err;	/* delay uevent until full sysfs population */	err = kobject_add(&mod->mkobj.kobj);	if (err)		goto out;	mod->holders_dir = kobject_add_dir(&mod->mkobj.kobj, "holders");	if (!mod->holders_dir) {		err = -ENOMEM;		goto out_unreg;	}	err = module_param_sysfs_setup(mod, kparam, num_params);	if (err)		goto out_unreg_holders;	err = module_add_modinfo_attrs(mod);	if (err)		goto out_unreg_param;	kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);	return 0;out_unreg_param:	module_param_sysfs_remove(mod);out_unreg_holders:	kobject_unregister(mod->holders_dir);out_unreg:	kobject_del(&mod->mkobj.kobj);	kobject_put(&mod->mkobj.kobj);out:	return err;}#endifstatic void mod_kobject_remove(struct module *mod){	module_remove_modinfo_attrs(mod);	module_param_sysfs_remove(mod);	kobject_unregister(mod->mkobj.drivers_dir);	kobject_unregister(mod->holders_dir);	kobject_unregister(&mod->mkobj.kobj);}/* * unlink the module with the whole machine is stopped with interrupts off * - this defends against kallsyms not taking locks */static int __unlink_module(void *_mod){	struct module *mod = _mod;	list_del(&mod->list);	return 0;}/* Free a module, remove from lists, etc (must hold module_mutex). */static void free_module(struct module *mod){	/* Delete from various lists */	stop_machine_run(__unlink_module, mod, NR_CPUS);	remove_sect_attrs(mod);	mod_kobject_remove(mod);	unwind_remove_table(mod->unwind_info, 0);	/* Arch-specific cleanup. */	module_arch_cleanup(mod);	/* Module unload stuff */	module_unload_free(mod);	/* This may be NULL, but that's OK */	module_free(mod, mod->module_init);	kfree(mod->args);	if (mod->percpu)		percpu_modfree(mod->percpu);	/* Free lock-classes: */	lockdep_free_key_range(mod->module_core, mod->core_size);	/* Finally, free the core (containing the module structure) */	module_free(mod, mod->module_core);}void *__symbol_get(const char *symbol){	struct module *owner;	unsigned long value, flags;	const unsigned long *crc;	spin_lock_irqsave(&modlist_lock, flags);	value = __find_symbol(symbol, &owner, &crc, 1);	if (value && !strong_try_module_get(owner))		value = 0;	spin_unlock_irqrestore(&modlist_lock, flags);	return (void *)value;}EXPORT_SYMBOL_GPL(__symbol_get);/* * Ensure that an exported symbol [global namespace] does not already exist * in the kernel or in some other module's exported symbol table. */static int verify_export_symbols(struct module *mod){	const char *name = NULL;	unsigned long i, ret = 0;	struct module *owner;	const unsigned long *crc;	for (i = 0; i < mod->num_syms; i++)	        if (__find_symbol(mod->syms[i].name, &owner, &crc, 1)) {			name = mod->syms[i].name;			ret = -ENOEXEC;			goto dup;		}	for (i = 0; i < mod->num_gpl_syms; i++)	        if (__find_symbol(mod->gpl_syms[i].name, &owner, &crc, 1)) {			name = mod->gpl_syms[i].name;			ret = -ENOEXEC;			goto dup;		}dup:	if (ret)		printk(KERN_ERR "%s: exports duplicate symbol %s (owned by %s)\n",			mod->name, name, module_name(owner));	return ret;}/* Change all symbols so that sh_value encodes the pointer directly. */static int simplify_symbols(Elf_Shdr *sechdrs,			    unsigned int symindex,			    const char *strtab,			    unsigned int versindex,			    unsigned int pcpuindex,			    struct module *mod){	Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;	unsigned long secbase;	unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);	int ret = 0;	for (i = 1; i < n; i++) {		switch (sym[i].st_shndx) {		case SHN_COMMON:			/* We compiled with -fno-common.  These are not			   supposed to happen.  */			DEBUGP("Common symbol: %s\n", strtab + sym[i].st_name);			printk("%s: please compile with -fno-common\n",			       mod->name);			ret = -ENOEXEC;			break;		case SHN_ABS:			/* Don't need to do anything */			DEBUGP("Absolute symbol: 0x%08lx\n",			       (long)sym[i].st_value);			break;		case SHN_UNDEF:			sym[i].st_value			  = resolve_symbol(sechdrs, versindex,					   strtab + sym[i].st_name, mod);			/* Ok if resolved.  */			if (sym[i].st_value != 0)				break;			/* Ok if weak.  */			if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)				break;			printk(KERN_WARNING "%s: Unknown symbol %s\n",			       mod->name, strtab + sym[i].st_name);			ret = -ENOENT;			break;		default:			/* Divert to percpu allocation if a percpu var. */			if (sym[i].st_shndx == pcpuindex)				secbase = (unsigned long)mod->percpu;			else				secbase = sechdrs[sym[i].st_shndx].sh_addr;			sym[i].st_value += secbase;			break;		}	}	return ret;}/* Update size with this section: return offset. */static long get_offset(unsigned long *size, Elf_Shdr *sechdr){	long ret;	ret = ALIGN(*size, sechdr->sh_addralign ?: 1);	*size = ret + sechdr->sh_size;	return ret;}/* Lay out the SHF_ALLOC sections in a way not dissimilar to how ld   might -- code, read-only data, read-write data, small data.  Tally   sizes, and place the offsets into sh_entsize fields: high bit means it   belongs in init. */static void layout_sections(struct module *mod,			    const Elf_Ehdr *hdr,			    Elf_Shdr *sechdrs,			    const char *secstrings){	static unsigned long const masks[][2] = {		/* NOTE: all executable code must be the first section		 * in this array; otherwise modify the text_size		 * finder in the two loops below */		{ SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL },		{ SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL },		{ SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL },		{ ARCH_SHF_SMALL | SHF_ALLOC, 0 }	};	unsigned int m, i;	for (i = 0; i < hdr->e_shnum; i++)		sechdrs[i].sh_entsize = ~0UL;	DEBUGP("Core section allocation order:\n");	for (m = 0; m < ARRAY_SIZE(masks); ++m) {		for (i = 0; i < hdr->e_shnum; ++i) {			Elf_Shdr *s = &sechdrs[i];			if ((s->sh_flags & masks[m][0]) != masks[m][0]			    || (s->sh_flags & masks[m][1])			    || s->sh_entsize != ~0UL			    || strncmp(secstrings + s->sh_name,				       ".init", 5) == 0)				continue;			s->sh_entsize = get_offset(&mod->core_size, s);			DEBUGP("\t%s\n", secstrings + s->sh_name);		}		if (m == 0)			mod->core_text_size = mod->core_size;	}	DEBUGP("Init section allocation order:\n");	for (m = 0; m < ARRAY_SIZE(masks); ++m) {		for (i = 0; i < hdr->e_shnum; ++i) {			Elf_Shdr *s = &sechdrs[i];			if ((s->sh_flags & masks[m][0]) != masks[m][0]			    || (s->sh_flags & masks[m][1])			    || s->sh_entsize != ~0UL			    || strncmp(secstrings + s->sh_name,				       ".init", 5) != 0)				continue;			s->sh_entsize = (get_offset(&mod->init_size, s)					 | INIT_OFFSET_MASK);			DEBUGP("\t%s\n", secstrings + s->sh_name);		}		if (m == 0)			mod->init_text_size = mod->init_size;	}}static void set_license(struct module *mod, const char *license){	if (!license)		license = "unspecified";	if (!license_is_gpl_compatible(license)) {		if (!(tainted & TAINT_PROPRIETARY_MODULE))			printk(KERN_WARNING "%s: module license '%s' taints "				"kernel.\n", mod->name, license);		add_taint_module(mod, TAINT_PROPRIETARY_MODULE);	}}/* Parse tag=value strings from .modinfo section */static char *next_string(char *string, unsigned long *secsize){	/* Skip non-zero chars */	while (string[0]) {		string++;		if ((*secsize)-- <= 1)			return NULL;	}	/* Skip any zero padding. */	while (!string[0]) {		string++;		if ((*secsize)-- <= 1)			return NULL;	}	return string;}static char *get_modinfo(Elf_Shdr *sechdrs,			 unsigned int info,			 const char *tag){	char *p;	unsigned int taglen = strlen(tag);	unsigned long size = sechdrs[info].sh_size;	for (p = (char *)sechdrs[info].sh_addr; p; p = next_string(p, &size)) {		if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')			return p + taglen + 1;	}	return NULL;}static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,			  unsigned int infoindex){	struct module_attribute *attr;	int i;	for (i = 0; (attr = modinfo_attrs[i]); i++) {		if (attr->setup)			attr->setup(mod,				    get_modinfo(sechdrs,						infoindex,						attr->attr.name));	}}#ifdef CONFIG_KALLSYMSstatic int is_exported(const char *name, const struct module *mod){	if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab))		return 1;	else		if (mod && lookup_symbol(name, mod->syms, mod->syms + mod->num_syms))			return 1;		else			return 0;}/* As per nm */static char elf_type(const Elf_Sym *sym,		     Elf_Shdr *sechdrs,		     const char *secstrings,		     struct module *mod){	if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {		if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)			return 'v';		else			return 'w';	}

⌨️ 快捷键说明

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