记录 axf 转 bin python 脚本笔记
记录 axf 转 bin python 脚本笔记
nixgnauhcuy前言
记录制作 .axf
文件转换为 .bin
文件的 python 脚本过程遇到的难题和思考,脚本地址是nixgnauhcuy/python_script (github.com)。
之前写过一篇 《关于嵌入式的bin、hex、axf、map》的文章,讲述了 .bin
、.hex
、.axf
、.map
文件的概念和用途,那个时候对 .axf
文件的理解过于片面,在制作脚本的过程中,发现了自己的不足,所以这次就来详细记录一下。
之前都是依赖于 fromelf.exe
工具来转换 .axf
文件为 .bin
文件,但是不知道具体的实现过程,就想自己体验一下这个流程,所以尝试用 python 实现。
准备工作
在制作脚本之前,我用 Keil 实现了某款芯片的程序,生成了 .axf
文件,然后使用 fromelf.exe
工具转换为 .bin
文件,这里生成的 .axf
文件和 .bin
文件就作为我后面验证脚本的输入文件和验证是否正确的输出文件。
初步实现
先分析 .axf
文件,打开后,第一反应,“WTF,这怎么看!”,
第一眼,一脸懵逼,无从下手,所以我用对比工具对比下,与 .bin
文件是否有关联,
对比完后,就发现了规律,.axf
的某一数据段正好完全等同于 .bin
文件。这就好办了,直接把 .axf
这一段数据取出,并且重新组成 .bin
文件即可。
从图里可以看出,.axf
开头的 0x00-0x34
这一段的内容是不需要的,所以要输出的 .bin
文件头索引,就要从 0x35
开始,而 .axf
输出的 .bin
文件的尾巴,内容是 0121002F0F0000022100000003010101
,所以我匹配到这一段数据后,我就认为是到顶了即可。
OK,思路有了,但是还要担心是不是所有的 .axf
文件都是这样的,先不管了,实现了再说,核心代码如下:
1 | AXF_HEAD_SIZE = 0x34 |
实现后,运行脚本后,结果一致,生成的文件符合预期,换了其他 MCU 的 .axf
文件和 .bin
文件,同样符合预期。
完善实现
虽然上面完成了,但是心里还是犯嘀咕,万一 AXF_HEAD_SIZE
不是从 0x34
开始,万一 BIN_END_MARK
刚好不匹配,岂不是执行不下,开始反思。
觉得自己对 .axf
没有理解,只是单纯的对比,发现逻辑并实现,跳过了对 .axf
文件的探索。
随后开始查询资料,查询 axf 如何 Convert 为 bin,发现好多资料都是提及使用 fromelf.exe
或者其他 xxx.exe
如何实现。
直到我看到了甲骨文 (oracle) 的文档,Chapter 7 Object File Format (Linker and Libraries Guide) (oracle.com),才发现之前的想法还是太幼稚了~
.axf
文件的文件格式如图,
根据给出的 ELF header 的结构体 Elf32_Ehdr
计算,长度正好符合前面提及的 0x34
,并且将数据解析后得到的 e_ehsize
内容,也就是标头长度同样是 0x34
,这样就验证了原先的逻辑,但是为了让程序更合理,我要获取的应该是 e_ehsize
的内容。
1 | #define EI_NIDENT 16 |
而 .bin
文件的相关又要获取 Program Header:
的内容,过程有点长,我就省略部分篇幅了,最终修正的核心代码如下:
1 | EI_NIDENT = 16 |
最终根据 ELF Header
和 ELF Program Headers
可以稳定正确的获取 .bin
文件的内容,脚本也算正确的完成了。
结语
整个实现过程还是发现很多不足,偷懒没有对 .axf
进行一个稍微深度的理解,停留在一个片面理解的程度就进行开发,反而耗费了更长的时间,不过过程中还是学到了不少东西,这波不亏~