设为首页 收藏本站
查看: 1361|回复: 0

SylixOS下Shell命令行执行模块内函数

[复制链接]

尚未签到

发表于 2018-8-26 10:33:26 | 显示全部楼层 |阅读模式
1. 适用范围
  本文档介绍了在Shell命令行执行内核模块内函数实现原理。
  在VxWorks中,系统自带有在Shell命令行直接执行驱动、应用内函数的功能,此功能完善了驱动开发工程师、应用开发工程师的开发、调试的手段。为了让这类工程师能快速适应SylixOS,据此开发了类似的功能模块,目前第一版支持在Shell命令行执行内核模块内的函数。
2. SylixOS内核模块动态加载原理
2.1 SylixOS中的ELF文件
  SylixOS中的ELF文件主要有三种:
  - obj文件: 一个源文件编译完成后,编译器将源文件内所有函数的指令块拼接形成TEXT节,将数据块拼接行成DATA节,同样还会根据需要生成其它节(如符号表、重定位表)。这些节拼接在一起形成obj文件。
  - 内核模块文件: 内核模块文件是多个obj文件组合形成的一个大文件,它将多个obj文件生成的TEXT节、DATA节、符号表、重定位表各自拼接为更大的TEXT节、DATA节、符号表和重定位表。
  - 位置无关ELF文件: SylixOS的应用程序和动态库都使用位置无关ELF文件格式,它支持代码段共享和写时拷贝。
2.2 内核模块的ELF文件格式
  内核模块包括ELF头、程序头表(也可以没有)和段节头表。
  2.2.1 ELF头
  ELF头描述了整个文件的基本属性,比如ELF文件版本,目标机器型号,程序入口地址等,如下所示。
typedef struct elf32_hdr {  
    unsigned char        e_ident[EI_NIDENT];         /*标示该文件为可执行的object文件     */
  
    Elf32_Half          e_type;                     /*标示object文件的类型             */
  
    Elf32_Half          e_machine;                  /*指出该object需要的体系结构        */
  
    Elf32_Word          e_version;                  /*确定object的文件版本             */
  
    Elf32_Addr          e_entry;                    /*是系统第一个传输控制的虚拟地址      */
  
    Elf32_Off           e_phoff;                    /*保持了程序头表在文件中的偏移量      */
  
    Elf32_Off           e_shoff;                    /*保持着段节头表在文件中的偏移量      */
  
    Elf32_Word          e_flags;                    /*保存着相关文件的处理器标志         */
  
    Elf32_Half          e_ehsize;                   /*保存着ELF头大小                  */
  
    Elf32_Half          e_phentsize;                /*一个程序头的大小                  */
  
    Elf32_Half          e_phnum;                    /*程序头表的个数                    */
  
    Elf32_Half          e_shentsize;                /*一个段节头的大小                  */
  
    Elf32_Half          e_shnum;                    /*段节头表中的段节头数目             */
  
    Elf32_Half          e_shstrndx;                 /*段节名字符表相关入口的段节头表索引   */
  
} Elf32_Ehdr;
  2.2.2 ELF文件头校验
  SylixOS中使用insmod命令或modulereg命令加载内核模块时,首先会读取ELF文件的文件头,并校验ELF文件头的有效性。
  在SylixOS中,ELF文件头的e_ident数值应固定为0x7f、‘E’、‘L’、‘F’四个字节;e_machine会根据arm、PowerPC、x86等不同架构为不同数值,以此来区分该ELF文件是否是架构适配的文件。
  2.2.3 获取内核模块版本
  SylixOS的ELF文件中都包含有“__sylixos_version”符号,该符号数值为一个字符串,字符串的内容为ELF内核模块版本。SylixOS将该版本与内核版本进行比较,确定ELF文件与SylixOS版本是否兼容。
2.3 ELF文件加载
  SylixOS会根据ELF文件头中的e_type数值对ELF文件进行不同种类的加载操作。ET_REL为可重定位文件,内核模块属于可重定位文件;ET_EXEC和ET_DYN为可执行文件,应用程序、动态库属于可执行文件。
  根据e_shentsize和s_shnum可以计算出整个ELF段节头表的大小,根据e_shoff可以获取ELF段节头表的偏移地址,由此将整个段节头表读入内存。
  根据每个段节头表中的每个段节头的信息可以获取每个段的类型、大小、存储地址,由此将每个段的内容读入内存。
  2.3.1 段节头
  段节头表中的每一个段节头都有如下所示的结构。
typedef struct {  
    Elf32_Word      sh_name;                        /* 段名称,值为段头字符表的索引   */
  
    Elf32_Word      sh_type;                        /* 段类型                     */
  
    Elf32_Word      sh_flags;                       /* 段属性                     */
  
    Elf32_Addr      sh_addr;                        /* 段在内存中的位置             */
  
    Elf32_Off       sh_offset;                      /* 段字节偏移量(从文件开始计数)   */
  
    Elf32_Word      sh_size;                        /* 段的字节大小                 */
  
    Elf32_Word      sh_link;                        /* 段报头表的索引连接            */
  
    Elf32_Word      sh_info;                        /* 保存额外信息                 */
  
    Elf32_Word      sh_addralign;                   /* 段地址对齐的约束              */
  
    Elf32_Word      sh_entsize;                     /* 段中每个入口的字节大小         */
  
} Elf32_Shdr;
  2.3.2 加载各个段
  首先为符号表、重定位段、字符串表申请内存,然后将这些段读入内存。
  符号表的sh_type为SHT_SYMTAB,重定位节的sh_type为SHT_RELA(带加数的重定位项)和SHT_REL(不带加数的重定位项),字符串表的sh_type为SHT_STRTAB。
  其次为数据段、代码段申请内存,并将数据段和代码段读入内存。
  2.3.3 重定位操作
  在处理目标文件时,链接器会遍历所有的重定位条目,碰到外部引用时,链接器会找到外部引用函数的确切地址,并且把它写回到指令操作数所占用的地址单元。像这样的操作,称之为重定位操作。对于每个需要重定位的代码段或数据段,都会有一个相应的重定位表。
  SylixOS加载内核模块时,会对重定位节进行重定位处理,本文对重定位暂不做具体分析。
2.4 导出符号表
  2.4.1 符号表
typedef struct elf32_sym {  
   Elf32_Word          st_name;                        /* 符号名                        */
  
   Elf32_Addr          st_value;                       /* 符号相应的值                   */
  
   Elf32_Word          st_size;                        /* 符号占用的字节大小              */
  
   unsigned char       st_info;                        /* 符号类型和绑定信息              */
  
   unsigned char       st_other;                       /* 目前为0                       */
  
   Elf32_Half          st_shndx;                       /* 符号所在的段                   */
  
} Elf32_Sym;

  •   符号类型


  •   STT_NOTYPE表示是未知类型符号;
  •   STT_OBJECT表示该符号是数据对象,比如变量、数组等;
  •   STT_FUNC表示该符号是个函数或其他可执行代码;
  •   STT_SECTION表示该符号表示一个段,这种符号必须是STB_LOCAL的;
  •   STT_FILE表示该符号表示文件名,一般都是该目标文件所对应的源文件名。
  符号作用域

  •   STB_LOCAL表示是局部符号,对于目标文件的外部不可见;
  •   STB_GLOBAL表示是全局符号,外部可见;
  •   STB_WEAK表示是弱引用。
  符号所在段

  •   SHN_UNDEF表示该符号未定义,该符号在本目标文件被引用到,但是定义在其他目标文件中;
  •   SHN_COMMON表示该符号是一个“COMMON块”类型的符号,一般来说,未初始化的全局符号定义就是这种类型。
  2.4.2 目前的导出符号表操作
  SylixOS中insmod命令或modulereg命令进行内核模块加载时,只会将全局符号进行导出。在模块控制块LW_LD_EXEC_MODULE中定义了符号缓冲,用于存储模块内的符号节点。当有符号需要导出时,从模块的符号缓冲内开辟内存节点,存储符号的字符串,符号的入口地址等信息。
  并且将该符号占用的所有内存节点按照哈希表排序,以方便快速查找与定位。
3. Shell命令行执行模块内函数实现
3.1 构建模块内部函数映射表
  由于目前系统只会对全局符号进行导出,导致当需执行模块内部非全局符号时就无法获取其入口地址,所以需要对模块内部函数构建函数映射表。
  构建模块内部函数映射表的流程与insmod的流程基本类似,需要重新对ELF文件进行解析,但是有两点区别:
  第一点,无需对函数进行重定位。因为内核模块此时已经加载,在获取函数的相对偏移地址后,只需获取内核模块加载在内存后的首地址,即可计算出内核模块内函数在内存中的实际地址。
  第二点,在导出符号时,应该修改过滤条件,使内部函数也可以加入到内核的符号缓冲中。
3.2 功能模块的使用
  3.2.1 解析模块ELF文件
  相关功能被制作成SymbolShell.ko,使用功能前首先加载SymbolShell.ko文件,同时加载测试用的test_module.ko,如下图所示。

  SymbolShell.ko会注册call命令,此命令提供了如下图所示的几个功能。

  3.2.2 打印模块内函数及其相对偏移
  该模块以会话的概念管理对某个模块内函数的调用,想调用某模块内的函数时,首先需要进入该模块的会话。
  以test_module.ko为例,如下图所示使用call –m test_module.ko命令进入test_module.ko的会话。然后使用call –l命令即可查看test_module.ko内的符号。

  3.2.3 执行模块内函数
  使用call test_func即可调用test_module.ko内的test_func函数,如下图所示,最终使用call –e命令可退出当前模块的会话。




运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-556721-1-1.html 上篇帖子: 如何在shell下免密码快速登陆MySQL数据库? 下篇帖子: shell 微信报警脚本
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表