免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2688 | 回复: 0
打印 上一主题 下一主题

[FreeBSD] freebsd9.2-内核支持的可执行文件格式 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-06-26 15:00 |只看该作者 |倒序浏览
在freebsd上,执行一个程序都是通过execve系统调用来实现的,但是在execve能够正确工作之前,内核需要进行
一系列的初始化并创建几个数据结构来支持execve系统调用的实现,比较重要的两个数据结构就是数组execsw和
数组elf_brand_list。在execve的实现中,数组execsw元素指向的对象包含的方法对具体的可执行文件格式进行解释,
而数组elf_brand_list用来设置struct proc(进程描述符)中的p_sysent成员,p_sysent成员和系统调用紧密联系,
相信在了解了execve的实现后,对系统调用的实现将有一个更深刻的理解。

freebsd支持多种可执行文件的格式,这意味着不同格式的可执行文件都可以在freebsd上执行,虽然内核不关心
普通文件的内容,但是对于可执行文件来说,内核必须能理解其文件格式。

对于支持的每种可执行文件格式,相应的实现都给内核提供一个接口,这个接口用来对相应的可执行文件格式进行
解释,该接口实际上是一个类型为struct execsw的结构体,如下所示:
  1. /*********************************************
  2. * ex_imgact:
  3.    一个函数,该函数负责对相应的可执行文件格式
  4.    进行解释。

  5.    ex_name:描述name的字符串。
  6. ***********************************/
  7.     64        struct execsw {
  8.     65                int (*ex_imgact)(struct image_params *);
  9.     66                const char *ex_name;
  10.     67        };

  11. /************************************************************************
  12. * Each of the items is a pointer to a `const struct execsw', hence the
  13. * double pointer here.
  14.    非常重要的execsw数组,在execve系统调用中使用,用来解释相应的
  15.    可执行文件,数组元素的类型为指向struct execsw数据对象的指针
  16. **************************************/
  17.    185        static const struct execsw **execsw;
复制代码
freebsd9.2现阶段支持的文件格式及其对应的struct execsw数据对象如下所示,由函数exec_register将
这些数据对象添加到execsw指针数组中:
  1. [release/9.2.0/sys/i386/linux/imgact_linux.c]-解释linux上的a.out文件格式:
  2.    235        /*
  3.    236         * Tell kern_execve.c about it, with a little help from the linker.
  4.    237         */
  5.    238        static struct execsw linux_execsw = { exec_linux_imgact, "linux a.out" };
  6.    239        EXEC_SET(linuxaout, linux_execsw);


  7. [release/9.2.0/sys/i386/ibcs2/imgact_coff.c]-解释通用文件对象格式:
  8.    489        /*
  9.    490         * Tell kern_execve.c about it, with a little help from the linker.
  10.    491         */
  11.    492        static struct execsw coff_execsw = { exec_coff_imgact, "coff" };
  12.    493        EXEC_SET(coff, coff_execsw);


  13. [release/9.2.0/sys/kern/imgact_gzip.c]-解释gzip文件格式:
  14.    389        /*
  15.    390         * Tell kern_execve.c about it, with a little help from the linker.
  16.    391         */
  17.    392        static struct execsw gzip_execsw = {exec_gzip_imgact, "gzip"};
  18.    393        EXEC_SET(execgzip, gzip_execsw);

  19. [release/9.2.0/sys/kern/imgact_aout.c]-解释a.out文件格式:
  20.    339        /*
  21.    340         * Tell kern_execve.c about it, with a little help from the linker.
  22.    341         */
  23.    342        static struct execsw aout_execsw = { exec_aout_imgact, "a.out" };
  24.    343        EXEC_SET(aout, aout_execsw);

  25. [release/9.2.0/sys/kern/imgact_shell.c]-解释shell脚本:
  26.    254        /*
  27.    255         * Tell kern_execve.c about it, with a little help from the linker.
  28.    256         */
  29.    257        static struct execsw shell_execsw = { exec_shell_imgact, "#!" };
  30.    258        EXEC_SET(shell, shell_execsw);

  31. [release/9.2.0/sys/compat/svr4/imgact_svr4.c]-解释svr4上的可执行文件格式:
  32.    233        /*
  33.    234         * Tell kern_execve.c about it, with a little help from the linker.
  34.    235         */
  35.    236        struct execsw svr4_execsw = { exec_svr4_imgact, "svr4 ELF" };
  36.    237        EXEC_SET(execsw_set, svr4_execsw);

  37. [release/9.2.0/sys/kern/imgact_elf.c]-解释elf文件格式:
  38.   2043  /*
  39.   2044   * Tell kern_execve.c about it, with a little help from the linker.
  40.   2045   */
  41. /***************************************************************************
  42. * static struct execsw elf32_execsw = {
  43.           exec_elf32_imgact,
  44.           "ELF32"
  45.    };
  46.    EXEC_SET(elf32,elf32_execsw);
  47. *************/
  48.   2046  static struct execsw __elfN(execsw) = {
  49.   2047          __CONCAT(exec_, __elfN(imgact)),
  50.   2048          __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE))
  51.   2049  };
  52.   2050  EXEC_SET(__CONCAT(elf, __ELF_WORD_SIZE), __elfN(execsw));
复制代码
下面以最通用的elf文件,来看看EXEC_SET的工作流程:
[step1]-展开EXEC_SET宏:
  1. static int elf32_modevent(module_t mod, int type,void *data)
  2. {
  3.    struct execsw *exec = (struct execsw *)data;
  4.    int error = 0;
  5.    switch (type) {
  6.       case MOD_LOAD:
  7.       error = exec_register(exec);
  8.       if (error)
  9.          printf("elf32 register failed\n");
  10.       break;

  11.       case MOD_UNLOAD:
  12.       error = exec_unregister(exec);
  13.       if (error)
  14.          printf("elf32 unregister failed\n");
  15.       break;

  16.       default:
  17.       error = EOPNOTSUPP;
  18.       break;
  19.    }

  20.    return error;
  21. }
  22. static moduledata_t elf32_mod = {
  23.          "elf32",
  24.          elf32_modevent,
  25.          (void *)&elf32_execsw
  26. };
  27. DECLARE_MODULE_TIED(elf32, elf32_mod, SI_SUB_EXEC, SI_ORDER_ANY);
复制代码
[展开宏DECLARE_MODULE_TIED]:
  1. static int elf32_modevent(module_t mod, int type,void *data)
  2. {
  3.    struct execsw *exec = (struct execsw *)data;
  4.    int error = 0;
  5.    switch (type) {
  6.       case MOD_LOAD:
  7.       error = exec_register(exec);
  8.       if (error)
  9.          printf("elf32 register failed\n");
  10.       break;

  11.       case MOD_UNLOAD:
  12.       error = exec_unregister(exec);
  13.       if (error)
  14.          printf("elf32 unregister failed\n");
  15.       break;

  16.       default:
  17.       error = EOPNOTSUPP;
  18.       break;
  19.    }

  20.    return error;
  21. }
  22. static moduledata_t elf32_mod = {
  23.          "elf32",
  24.          elf32_modevent,
  25.          (void *)&elf32_execsw
  26. };

  27. static struct mod_depend _elf32_depend_on_kernel = {       
  28.         __FreeBSD_version,                                               
  29.         __FreeBSD_version,                                               
  30.         __FreeBSD_version                                               
  31. };
  32.                                                                
  33. static struct mod_metadata _mod_metadata_md_elf32_on_kernel = {       
  34.        MDT_STRUCT_VERSION,                                       
  35.        MDT_DEPEND,                       
  36.        &_elf32_depend_on_kernel,                       
  37.        "kernel"                                                       
  38. };                                                               
  39. DATA_SET(modmetadata_set, _mod_metadata_md_elf32_on_kernel);

  40. static struct mod_metadata _mod_metadata_md_elf32 = {       
  41.        MDT_STRUCT_VERSION,                                       
  42.        MDT_MODULE,                       
  43.        &elf32_mod,                               
  44.        "elf32"                                                       
  45. };                               
  46. DATA_SET(modmetadata_set, _mod_metadata_md_elf32);
  47.        
  48. SYSINIT(elf32module, SI_SUB_EXEC, SI_ORDER_ANY, module_register_init, &elf32_mod);
  49. struct __hack;
复制代码
从上面的展开过程可以得出:
1:内核对负责解释相应可执行文件格式这部分源代码是以模块的方式管理。

2:定义了一个对该模块具体事件进行响应的回调函数。

3:定义并初始化了几个描述模块的数据结构。

4:将类型为struct mod_metadata数据对象的地址保存到name为"set_modmetadata_set"的section中,
   在SI_SUB_KLD对应的子系统中由初始化函数linker_init_kernel_modules处理name为"set_modmetadata_set"
   的section,并且创建描述可执行文件格式的struct module对象,并将其链接到相应的链表中,
   这个处理过程在SI_SUB_EXEC对应的子系统初始化之前执行。

5:通过SYSINIT机制来对模块进行相应的初始化,由初始化函数module_register_init来完成,同时用
   有意义的值初始化execsw数组。
  1.    104                SI_SUB_KLD                = 0x2000000,        /* KLD and module setup */
  2.    143                SI_SUB_EXEC                = 0x7400000,        /* execve() handlers */
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP