DSP

用Python分析COFF文件

2019-07-13 16:25发布

      TI的编译器,连接器等工具产生的目标文件格式为Common Object File Format(简称COFF)。COFF格式是AT&T开发的,在UNIX系统中所采用的目标文件格式。TI的编译器产生的obj文件以及连接之后产生的out文件都是COFF格式的。用CCS载入out文件到DSP的内存的时候,CCS会分析这个out文件,将其中储存的代码段和初始数据等段中的数据复制到DSP的内存中,并且设置程序指针到Entry Point(入口地址)。Hex5x, Hex6x等转换工具通过分析out文件,将其输出为一个boot table,方便各种自举(自启动)程序的编写。例如我们经常把这样的boot table写入flash, 制作成能从flash自举的应用程序。 了解COFF文件的格式,有助于我们了解一些自启动的细节,明白CCS loader和hex转换工具的工作原理,或者编写一些特殊用途的启动程序。例如多启动或者部分更新正在运行的程序等等。 在TI的文档中有COFF文件格式的详细介绍。例如TMS320C55x Assembly Language Tools User’s Guide或者TMS320C6000 Assembly Language Tools User's Guide等。文档很详细,下面只是简单介绍一下COFF文件的基本构造。 COFF最开始是文件头和附加文件头,附加文件头中保存有Entry Point的地址。其后就是Section Header表,其中有各个section的物理地址、长度以及初始化数据的在文件中的偏移地址等信息。所有的section header结束之后就是数据区了。也就是需要复制到DSP 内存中去的数据。其后还有连接用的relocation信息,如果out文件的话不需要这些信息,relocation之后是符号表,例如C语言的全局变量,函数等符号都在这个表中储存。最后是字符串表,section的名称或者符号名称太长的时候就把这些名称字符串储存到字符串表中
根据这样的结构,自己动手写一个out->boot table的程序其实也很简单,只需要从out文件中获取entry pointer、需要复制的各个section的地址、长度以及数据即可。 这里给出一个Python程序示范:COFF Reader,它可以显示出out文件的结构。此程序只是一个示范,并无实用价值,参照它阅读COFF格式的文档也许会更加容易一些。运行此程序需要事先在电脑中安装Python 2.4。解压之后运行coff.py文件即可。   COFF文件一共有8种数据,自上而下分别为:   1. 文件头(File Header)   2. 可选头(Optional Header)   3. 段落头(Section Header)   4. 段落数据(Section Data)   5. 重定位表(Relocation Directives)   6. 行号表(Line Numbers)   7. 符号表(Symbol Table)   8. 字符串表(String Table)   其中,除了段落头可以有多个节(因为可以有多个段落)以外,其它的所有类型的节最多只能有一个。   文件头:顾名思义,它就是COFF文件的头,它用来保存COFF文件的基本信息,如文件标识,各个表的位置等等。   可选头:再顾名思义,它也是一个头,还是可选的,而且可有可无。在目标文件中,基本上都没有这个头;但在其它的文件中(如:可执行文件)这个段用来保存在文件头中没有描述到的信息。   段落头:又顾……(不顾了,再顾有人要打我了J),这个头(怎么这么多的头啊?!)是用来描述段落信息的,每个段落都有一个段落头来描述。段落的数目在文件头中会指出。   段落数据:这通常是COFF文件中最大的数据段,每个段落真正的数据就保存在这个位置。至于怎么区分这些数据是哪个段落的,不要问我,去问段落头。   重定位表:这个表通常只存在于目标文件中,它用来描述COFF文件中符号的重定位信息。至于为什么要重定位,请回家看看你的操作系统的书籍。   符号表:这个表用来保存COFF文件中所用到的所有符号的信息,连接多个COFF文件时,这个表帮助我们重定位符号。调试程序时也要用到它。   字符串表:不用我说,大家也知道它用来保存字符串的。可是字符串保存给谁看呢?不知道了吧!?问我啊!J符号表是以记录的形式来描述符号信息的,但它只为符号名称留置了8个字符的空间,早期的小程序还将就能行,可在现在的程序中,一个符号名动不动就数十个字符,8个字符怎么能够?没办法,只好把这些名称存在字符串表中。而符号表中只记录这些字符串的位置。