注:最近在做热补丁的功能,看到一篇gateway写的文章,觉得很通俗易懂的,就将搜集到的资料又整理了一下,供大家参考。

使用动态加载目标模块的方式有很多好处,比如可以在不破坏原来的环境下增加调试定位功能,相当于给系统打“补丁”,不需要编译原来的代码(甚至可以不用原来的代码)而只需要关注正在调试的代码,这样能减少编译时间和减少映像的加载量。

实现目标模块的动态加载有很多种方法,如在主机环境的界面上通过在目标模块上单击鼠标右键,选择“Download 文件名”;也可以通过wShell和GDB命令行窗口实现。本文通过tshell下使用ld()、loadModule()、loadModuleAt()中一个函数来实现,当然在代码中也可以自如地调用它们。

ld命令是由用户接口子程序库usrLib提供的一个加载命令。使用ld的前提是在config.h中定义INCLUDE_LOADER。这样,在usrRoot()函数中就会自动调用加载模块初始化函数moduleLibInit();同时,根据CPU类型,自动决定目标模块的格式。如果CPU是MIPS、PPC、ARM、I80X86、COLDFIRE、SIMSPARCSOLARIS、SH等,加载的目标模块格式是elf类型,就会调用loadElfInit();如果CPU是I960、AM29XXX等,加载的目标模块的格式则是coff类型,就会调用loadCoffInit()函数。

在ARM和PPC下,Tornado编译器生成的.o或.out都是elf类型,打开目标文件都会看到文件头有ELF(45,4C,46)标记。这时可以通过ftp工具把它加载到文件系统(如使用copy命令加载到RAM盘)中,再调用ld()或loadModule()函数加载到内存中运行。

ld的函数原型是:MODULE_ID ld( int syms, BOOL noAbort, char *name )。参数syms决定目标文件的符号怎么处理:0,添加全局符号到系统符号表中;1,添加全局和局部符号到系统符号表中;-1,符号不添加到系统符号表中。一般选1,便于在shell下使用其中的符号。参数noAbort表明是否可以忽略加载期间出现的错误,为TRUE则忽略,FALSE则不忽略。name则为加载的文件名,包含文件路径。注意:ld是一条shell命令,也就是它是为在shell下调用而设计的一个函数,所以尽量不要用在代码内部,因为在之后的vxworks版本中直接调用ld可能会不支持。

loadModule的函数原型是:MODULE_ID loadModule( int fd, int loadFlag )。fd为文件描述符号,需要先打开文件获取fd;参数loadFlag含义有LOAD_NO_SYMBOLS(2)、LOAD_LOCAL_SYMBOLS(4)、LOAD_GLOBAL_SYMBOLS(8)、LOAD_ALL_SYMBOLS(0xC)三种。

假如已经将需要加载的文件demo.o放到ram盘中,则加载到内存中的方式有以下几种:

(1)-> ld(1,0,”/tffs0/demo.o”)

(2)-> ld </tffs0/demo.o

(3)-> fd = open(“/tffs0/demo.o”,O_RDONLY);

-> loadModule(fd,0xC);

->close(fd);

加载函数返回的是MODULE_ID,这是该加载模块的标识,使用卸载unldByModuleId时可以模块ID。查看加载模块的具体信息的函数是moduleShow()。

对于某些应用,使用ld或loadModule会出现以下错误:

Relocation value does not fit in 24 bits.

ld error: error loading file (errno = 0x3d0001).

这个问题主要在内存空间大于32M,当往目标机上downloading编译好的模块时出现。

原因:

VxWorks和GNU/Wind River(diab)compiler要遵循EABI(Embedded Application Binary Interface),这是PowerPC架构的一个标准。这个标准对函数的调用是branching而不是jumping,而branching在 PowerPC架构下面是限制在32M以内的。(The PowerPC relative branch instruction is limited to jumps between +/- 32MB (24 bits = +/- 4M instructions, 4 bytes per instruction = +/- 32MB) of the current instruction. If an instruction cannot be resolved within a 24 bit range, it will print out the error above.)

一般来说,如果通过主机往目标机download,是不会出现这个问题的,因为这个时候的目标文件(比如.out文件)是download到了 WDB POOL里面,而WDB POOL是紧挨着VxWorks映像的,所以只要WDB POOL有足够大的空间就不会出现上述问题。

而通过目标机download(比如tshell)时,目标文件是download到系统内存池的最后,这个时候如果你的内存大于32M,就会出现上述问题。

为了规避这个问题,可以使用长跳转来完成函数的调用。可以通过在C/C++ compiler下加入编译选项解决。对于GNU,该选项是-mlongcall;对于diab,该选项是-Xcode-absolute-far。

当然也可以使用loadModuleAt()解决这个问题,将目标模块加载到指定地址,使所需要的函数在跳转地址以内。其原型是:MODULE_ID loadModuleAt( int fd, int loadFlag, void **ppText, void **ppData, void **ppBss)。ppText、ppData、ppBss分别是加载后的text段、data段和bss段所指向的地址。假如加载demo.o到1M空间处(保证这个空间没有被占用):

-> fd = open(“/tffs0/demo.o”,O_RDONLY);

-> pText = 0x100000; pData = pBss = 0xffffffff; /* (LD_NO_ADDRESS) */

-> loadModuleAt( fd, 8, &pText, &pData, &pBss);close(fd);

加载完成后,在shell下就可以执行最新的目标文件中的函数了。如果函数以前有的,按照最后加载的函数为准。可见,加载的目标模块都经过重定位、符号解析和添加的过程。

如果目标模块中使用的全局变量或函数在本模块和以前的程序中都没有定义,则加载时会出现类似undefined symbol的错误。

有时候从主机上下载的目标模块中的函数符号不会出现在目标机的shell中,反过来也一样,目标机的shell中生成的符号对主机wShell也不可见。出现这种情况的主要原因是目标机和主机的符号没有同步化,需要在编译映像时定义INCLUDE_SYM_TBL_SYNC.

VxWorks动态加载相关推荐

  1. VxWorks动态加载.out文件

    //Device.cpp #include "other.h" #ifdef __cplusplus extern "C" { #endif  int init ...

  2. js 动态加载select触发事件

    动态加载select后,手动调用一下 subjectChange函数,模拟触发change事件 function hallidChange(value) {$.ajax({type: "po ...

  3. cascader 动态加载 回显_ElementUI cascader级联动态加载回显和搜索看这个就够了

    这一篇是上一次讨论cascader级联动态加载回显问题的延续,文末有链接. 以下是思考和开发的过程,不感兴趣可以直接看使用文档. https://github.com/zhuss/lazy-casca ...

  4. C#动态加载DLL(转)

    利用反射进行动态加载和调用. Assembly ass=Assembly.LoadFrom(DllPath); //利用dll的路径加载 加载dll后,需要使用dll中某类. Type type=as ...

  5. 利用反射实现类的动态加载

    为什么80%的码农都做不了架构师?>>>    //首先定义一个接口来隔离类: public interface Operator { // public java.util.Lis ...

  6. 利用 JQuery的load函数动态加载页面

    利用JQuery的load函数动态加载页面 JQuery有好多Ajax函数,其中load是用来动态加载一个页面的内容到指定的dom元素上. 我们来做个例子: 做一个上下(左右)结构的页面,其中下左部分 ...

  7. 插件化知识梳理(7) 类的动态加载入门

    一.前言 在 插件化知识梳理(6) - Small 源码分析之 Hook 原理 这一章的学习完成之后,下一步我们将进入插件化加载的精髓,动态加载类的学习,在此之前,我们需要先准备一些关于类加载的知识. ...

  8. spark-submit --files 动态加载外部资源文件

    在做spark时,有些时候需要加载资源文件,需要在driver或者worker端访问.在client模式下可以使用IO流直接读取,但是在cluster模式下却不能直接读取,需要如下代码: val is ...

  9. Android动态加载jar/dex

    http://www.cnblogs.com/over140/archive/2011/11/23/2259367.html 加载jar boolean bool = new File("/ ...

最新文章

  1. c++ vector pop_back() 与pop_back()
  2. 计算机系统基础 南京大学,计算机系统基础(一):程序的表示、转换与链接
  3. codevs——2853 方格游戏(棋盘DP)
  4. AjaxPro怎么用
  5. html的属性与css的属性,HTML的属性和css基础
  6. 0编译器详解_详解Java枚举类型(Enum)中的方法
  7. “附近的小程序”可以直接找“餐饮” 非管理员也能登录小程序了
  8. GO string 转map_用go语言,只需两百行代码就能搞定并发聊天室!
  9. postgreSQL源码分析——索引的建立与使用——Hash索引(2)
  10. ServicePointManager.ServerCertificateValidationCallback 冲突的解决
  11. [抄]使用网页进行展示而非PPT
  12. win11检测不到第二屏幕怎么办 windows11检测不到第二屏幕的解决方法
  13. Mac如何删除python Python cannot be opened because of a problem
  14. C++例4.11 求两个或三个正整数中的最大数,用带有默认参数的函数实现。
  15. Cartographer 源码解析1.1 —— 算法整体结构
  16. CPAN | 配置阿里源
  17. 网络攻防原理与技术 第一章 课后题
  18. 文本摘要评测工具ROUGE的搭建和测试
  19. YOLOv3代码阅读笔记之utils.py(第六篇)
  20. Android 7.0 Nougat正式版新特性

热门文章

  1. 计算机组成原理中ID是什么,计算机组成原理.doc
  2. 怀化学院计算机科学专业排名,2019怀化学院专业排名
  3. python中什么最重要_Python 3中被忽视了的三大重要功能
  4. 标签 href 怎么拼接_【微信】用户-标签的兴趣建模
  5. 移植uboot之修改代码支持NorFlash记录
  6. 移动混合开发之android文件管理新建文件和删除文件
  7. for in / for of 要会用
  8. Arch Linux 安装总结
  9. 《DSP using MATLAB 》示例Example6.3
  10. 利用curl验证ssl网站(webservice)