本文针对的是binutils-2.24版本。分享一些研究体会,欢迎指正不足之处。分析任何一款超过上百兆的软件,其实难点就是哪些概念、哪些需求和结果。

零基础入门学习汇编语言教程(学习汇编器gas理解bfd)(1)

如上图。整个binutils-2.24的系列工具,都是围绕“二进制结果文件描述bfd”展开的。例如,gas汇编输出的.o目标文件就是一种二进制文件(通常采用ELF格式),ld连接输出的.so共享库文件或exe可执行文件也是一种二进制文件(通常采用ELF格式),ar输入输出的也是一种二进制文件(通常是.a静态库文件)。对应bfd的成员,如bfd_ELF结果对象elf_obj_tdata==bfd->tdata.elf_obj_data 或 bfd_库结果对象artdata==bfd->tdata.aout_ar_data,这是根据bfd结果格式bfd->format==bfd_format和bfd目标机结果格式bfd_flavour==bfd_target->flavour进行判断的结果。

零基础入门学习汇编语言教程(学习汇编器gas理解bfd)(2)

二进制结果文件描述bfd进行"gas/ld/ar/objdump"等操作的结果,就是bfd结果对象,可以是bfd_ELF结果对象elf_obj_tdata、bfd_库结果对象artdata 等。

二进制结果文件描述bfd可进行bfd结果文件的具体操作(成员filename,iostream,where),并由此来指明“可写bfd、可读bfd”。

二进制结果文件描述bfd必须指明“所针对的 bfd指令架构信息bfd_arch_info”,如mips/arm/x86的某个架构信息。

二进制结果文件描述bfd必须指明“所针对的 bfd目标机信息bfd_target”,如mips/arm/x86的某个目标机信息。

bfd节区链表bfd->sections[]就是用来存储“各个节区的代码和数据信息”,不同节区特征或不用用途的节区,通常作为不同的各个节区。而单个通常节区的内容是如何形成的呢?如某个通常节区内,有系列的指令操作和伪操作,分别形成“系列的编码碎片frag”。针对编码长度是确定的连续指令操作,和1个编码长度可变化的指令操作或伪操作,将作为1个编码碎片frag。某个通常节区的内容,其实就是一串“编码碎片frag”。

如果指令操作或伪操作中含有需要解析的符号(式),和重定位型号,这是想求解 符号(式)的值,我称之为“解值fix”。通常可以说,产生【该解值符号项(fx_addsy-fx_subsy fx_offset),该重定位型号,是否相对PC地址的,应用fx_frag,定长区编码地址偏移,解值字节数的】解值fix。可以这样简单理解,解值fix就是在某个编码碎片frag上的某个地址上符号的求解或重定位。

所以gas实现的write_object_file()的前期操作,就是针对“各个节区的串联frag和串联解值fix”,进行遍历操作。

,