freebsd9.2-创建elf文件格式对应的struct module对象
-处理name为"set_modmetadata_set"的section中保存的数据:/*********************************************************************** typedef struct linker_file* linker_file_t;
linker_file_t linker_kernel_file;
对于内核本身,在初始化阶段,会创建一个struct linker_file类型
的数据对象来描述内核本身。全局变量linker_kernel_file指向描述内核
本身的struct linker_file对象。
当使用kldload系统调用加载一个模块时,内核也会为该模块创建
一个struct linker_file类型的数据对象来描述该模块。
函数linker_init_kernel_modules是一个简单的封装函数。
****************/
366static void
367linker_init_kernel_modules(void)
368{
369
370 linker_file_register_modules(linker_kernel_file);
371}
325static int
326linker_file_register_modules(linker_file_t lf)
327{
328 struct mod_metadata **start, **stop, **mdp;
329 const moduledata_t *moddata;
330 int first_error, error;
331
332 KLD_DPF(FILE, ("linker_file_register_modules: registering modules"
333 " in %s\n", lf->filename));
334
/*****************************************************************************************
* 335-347:
确定name为"set_modmetadata_set"的section的起始地址和结尾地址,起始地址和结尾地址
分别通过变量start和stop返回。
*
*************************************/
335 if (linker_file_lookup_set(lf, "modmetadata_set", &start,
336 &stop, NULL) != 0) {
337 /*
338 * This fallback should be unnecessary, but if we get booted
339 * from boot2 instead of loader and we are missing our
340 * metadata then we have to try the best we can.
341 */
342 if (lf == linker_kernel_file) {
343 start = SET_BEGIN(modmetadata_set);
344 stop = SET_LIMIT(modmetadata_set);
345 } else
346 return (0);
347 }
/****************************************************************************************
* 349-362:依次处理name为"set_modmetadata_set"的section的数据,这里的数据就是类型为
struct mod_metadata的数据对象的地址,并且只处理类型为MDT_MODULE的
struct mod_metadata的数据对象。
这里以一个实例来简要分析一下,看看module_register函数到底做了什么工作:
static struct mod_metadata _mod_metadata_md_elf32 = {
MDT_STRUCT_VERSION,//md_version成员
MDT_MODULE, //md_type成员
&elf32_mod, //md_data成员
"elf32" //md_cval成员
};
352:moddata此时的值就为&elf32_mod。
355:调用函数module_register,该函数
**************************************/
348 first_error = 0;
349 for (mdp = start; mdp < stop; mdp++) {
350 if ((*mdp)->md_type != MDT_MODULE)
351 continue;
352 moddata = (*mdp)->md_data;
353 KLD_DPF(FILE, ("Registering module %s in %s\n",
354 moddata->name, lf->filename));
355 error = module_register(moddata, lf);
356 if (error) {
357 printf("Module %s failed to register: %d\n",
358 moddata->name, error);
359 if (first_error == 0)
360 first_error = error;
361 }
362 }
363 return (first_error);
364}[在看module_register函数之前,先熟悉一点数据结构]:/******************************************************************************
* link:
链接到modules链表中
struct {
struct module *tqe_next;/* next element */
struct module **tqe_prev; /* address of previous next element */
TRACEBUF
}link;
flink:
链接到struct linker_file对象的modules成员中
struct {
struct module *tqe_next;/* next element */
struct module **tqe_prev; /* address of previous next element */
TRACEBUF
}flink;
file:包含该module的linker file
refs:引用计数器。
name: module的名字,一般为struct moduledata对象的name成员,
module_lookupbyname函数使用.
id:module的唯一标识符,从1开始分配,module_lookupbyid函数使用.
handler:相应module的处理函数,一般为struct moduledata对象的evhand成员.
arg:handler所需的参数,一般为struct moduledata对象的priv成员.
* data:moduel指定的数据 .
***************************/
49struct module {
50 TAILQ_ENTRY(module) link; /* chain together all modules */
51 TAILQ_ENTRY(module) flink;/* all modules in a file */
52 struct linker_file *file;/* file which contains this module */
53 int refs; /* reference count */
54 int id; /* unique id number */
55 char *name;/* module name */
56 modeventhand_t handler; /* event handler */
57 void *arg; /* argument for handler */
58 modspecific_t data; /* module specific data */
59};[变量modules]-modules链接了注册到内核的全部struct module数据对象:static TAILQ_HEAD(modulelist, module) modules;
struct modulelist {
struct module *tqh_first;
struct module **tqh_last;
TRACEBUF
}modules;[函数module_register]:/*********************************************************************
* static moduledata_t elf32_mod = {
"elf32", //name成员
elf32_modevent,//evhand成员
(void *)&elf32_execsw //priv成员
};
参数描述:
data:&elf32_mod。
container:linker_kernel_file。
*********************************/
151 int
152 module_register(const moduledata_t *data, linker_file_t container)
153 {
154 size_t namelen;
155 module_t newmod;
156
/*************************************************************************************
* 158-164:
函数module_lookupbyname在modules链表中查找name为"elf32"的module,
如果已经存在,就返回一个错误码。
165-170:
执行到这里的话,就表示要创建一个name为"elf32"的module,此时分配
一个大小为sizeof(struct module) + namelen的内存空间,用来保存描述
该module的struct mopdule对象和module的name。
这里将name为"elf32"的module对应的struct module对象简记为elf32_module。
171-177:初始化相关的成员。
static int nextid = 1;
175:elf32_module的handler成员设置为elf32_modevent函数的地址。
176:elf32_module的arg成员设置为&elf32_execsw。
178:将elf32_module链接到modules链表中。
180-181:根据情况将elf32_module链接到struct linker_file对象的modules链表中。
*****************************************************/
157 MOD_XLOCK;
158 newmod = module_lookupbyname(data->name);
159 if (newmod != NULL) {
160 MOD_XUNLOCK;
161 printf("module_register: module %s already exists!\n",
162 data->name);
163 return (EEXIST);
164 }
165 namelen = strlen(data->name) + 1;
166 newmod = malloc(sizeof(struct module) + namelen, M_MODULE, M_WAITOK);
167 if (newmod == NULL) {
168 MOD_XUNLOCK;
169 return (ENOMEM);
170 }
171 newmod->refs = 1;
172 newmod->id = nextid++;
173 newmod->name = (char *)(newmod + 1);
174 strcpy(newmod->name, data->name);
175 newmod->handler = data->evhand ? data->evhand : modevent_nop;
176 newmod->arg = data->priv;
177 bzero(&newmod->data, sizeof(newmod->data));
178 TAILQ_INSERT_TAIL(&modules, newmod, link);
179
180 if (container)
181 TAILQ_INSERT_TAIL(&container->modules, newmod, flink);
182 newmod->file = container;
183 MOD_XUNLOCK;
184 return (0);
185 }
页:
[1]