Binutils 新目标架构移植指南

本文详述了将Binutils移植到新架构的过程,包括理解Binutils的文件组织结构,如BFD、opcodes、binutils、gas和ld等组件,以及构建和测试新移植的工具。主要介绍了在移植过程中涉及的数据结构、头文件、目标文件格式和特定架构的代码修改。
摘要由CSDN通过智能技术生成


虽然 binutils 项目已有一个 100 页的内部指南,但是撰写本文主要针对那些第一次想要开发/移植binutils的人。并且官方指南还存在以下限制:

  1. 它倾向于记录得详细一些,因此,单个函数描述得很清楚,但很难了解binutils的整体情况。
  2. 它并不完整,许多最有用的部分(例如,最终重定位的细节)尚未编写。

当前想把 binutils 移植到新架构的开发人员都是通过阅读源代码和查看其他架构是如何移植的来了解binutils是如何工作的。

我本人在将 binutils 移植到 Compact-RISC(又名 CR16)架构时也经历了这个过程,故本文旨在记录学习经验,以帮助他人,特别是那些希望将 binutils 工具移植到新target的人。

Binutils文件组织结构

binutils 源代码主体位于少数目录中,其中某些组件是在内部以及其他项目中使用的库。例如,BFD 库用于 GNU GDB 调试器。这些库有自己的顶级目录。主要目录如图1所示。
Alt
以下是有关这些目录的一些简短信息:

  • include/ 包含跨主要组件信息的头文件。例如,由于主模拟器将 GDB (在gdb/目录中) 链接到模拟器 (在sim/目录中),因此,它的接口 header 在此处 (remote-sim.h)。针对特定组件的其他header保存在该组件的目录中。
  • bfd/ 包含二进制文件描述符库。该库包含处理特定二进制文件格式的代码,例如 ELF、COFF、SREC 等。如果必须识别新的目标文件类型,则应在此目录添加支持它的代码。
  • opcodes/ 包含操作码库,有关于如何汇编和反汇编指令的信息。
  • cpu/ 包含名为 CGEN 的实用程序的源文件。该工具可用于自动为opcodes库以及 GDB 使用的 SIM 模拟器生成 target-specific 源文件。
  • binutils/ 虽然这么命名,但这并不是 binutils 的主目录。相反,它是所有没有自己顶级源目录的 binutils 工具的目录,包括objcopyobjdumpreadelf等工具。
  • gas/ 包含 GNU 汇编器。 target-specific 汇编代码保存在config/子目录中。
  • ld/ 包含 GNU 链接器。 target-specific 链接器文件保存在子目录中。
  • gprof/ 包含 GNU 分析器。该程序没有任何 target-specific 代码。
  • gold/ 包含新的 GNU 链接器。这是一个正在创建的新链接器,用于替换 LD,目前它仍在开发中。
  • elfccp/ 包含elfcpp,一个用于读写 ELF 信息的 C++ 库。目前仅由 GOLD 链接器使用。

此外,在 binutils 源代码版本的顶层还可以找到一些其他目录,它们在 binutils 构建过程中使用,但不是 binutils 项目的一部分。

  • intl/ 包含来自gettext的 GNU gettext 库。
  • libiberty/ 在 POSIX 和glibc出现之前,这是一个提供一组标准函数的GNU项目。它存在于 binutils ,最有价值的就是其免费存储管理和参数解析功能。

主要功能区和数据结构

二进制文件描述

二进制文件描述 (BFD) 是一个包,无论目标文件格式如何,它都允许应用程序使用相同的例程来操作目标文件。只需创建新的 BFD 后端并将其添加到库中就可以支持新的目标文件格式。

BFD库后端创建了多个数据结构,这些数据结构描述了存储在特定类型目标文件中的数据。最后,为每个单独的架构定义了一个唯一的枚举常量(类型为enum bfd_architecture)。该常量随后可被用于访问与特定架构相关的各种数据结构。

对于 Compact-RISC,16 位实现(可能是 COFF 或 ELF 二进制文件)的枚举常量为bfd_cr16_arch。它可用于访问各种结构体,例如:

  const bfd_arch_info_type bfd_cr16_arch =
    {
      16,               /* 16 bits in a word.  */
      32,               /* 32 bits in an address.  */
       8,               /*  8 bits in a byte.  */
      bfd_arch_cr16,    /* enum bfd_architecture arch.  */
      bfd_mach_cr16,    /* Machine value, used to distinguish between cr16 variants.  */
      "cr16",           /* Architecture name (short version).  */
      "cr16",           /* Architecture name (long version).  */
      1,                /* Section alignment power.  */
      TRUE,             /* True if this is the default machine for the architecture.  */
      bfd_default_compatible, /* Function to call to determine if two different architectures are compatible.  */
      bfd_default_scan, /* Function to call to determine if a given string matches this architecture.  */
      NULL,             /* Pointer to the next CR16 machine architecture.  */
    };

这个特定的结构体定义在bfd/cpu-<target>.c文件中。

文件<file_format>-<target>.c(例如,elf32-cr16.c)用于为给定的文件格式和架构提供 target-specific 支持。它至少提供了以下信息:

  1. 将 BFD 重定位枚举映射到 target-specific 重定位类型的reloc_map数组。
  2. 具有 target-specific 重定位详细信息的数组reloc_howto_type。以下是来自 cr16 移植的数组 entry :
  (R_CR16_NONE,              /* Type.  */
   0,                        /* Rightshift.  */
   2,                        /* Size.  */
   32,                       /* Bitsize.  */
   FALSE,                    /* PC_relative */
   0,                        /* Bitpos */
   complain_overflow_dont,   /* Complain_on_overflow */
   bfd_elf_generic_reloc,    /* Special_function */
   "R_CR16_NONE",            /* Name */
   FALSE,                    /* Partial_inplace */
   0,                        /* Src_mask */
   0,                        /* Dst_mask */
   FALSE),                   /* PCREL_offset */
  1. 通过使用与目标相关的配置来定义下面的宏:
#define TARGET_LITTLE_SYM
#define TARGET_LITTLE_NAME

#define ELF_ARCH
#define ELF_MACHINE_CODE
#define ELF_MAXPAGESIZE
#define elf_symbol_leading_char

#define elf_info_to_howto
#define elf_info_to_howto_rel

#define elf_backend_relocate_section
#define elf_backend_gc_mark_hook
#define elf_backend_gc_sweep_hook
#define elf_backend_can_gc_sections
#define elf_backend_rela_normal
#define elf_backend_check_relocs
#define elf_backend_final_write_processing
#define elf_backend_object_p
#define elf_backend_create_dynamic_sections
#define elf_backend_adjust_dynamic_symbol
#define elf_backend_size_dynamic_sections
#define elf_backend_omit_section_dynsym
#define elf_backend_finish_dynamic_sections
#define elf_backend_reloc_type_class
#define elf_backend_want_got_plt
#define elf_backend_plt_readonly
#define elf_backend_want_plt_sym
#define elf_backend_got_header_size

#define bfd_elf32_bfd_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup
#define bfd_elf32_bfd_relax_section
#define bfd_elf32_bfd_get_relocated_section_contents
#define bfd_elf32_bfd_merge_private_bfd_data
#define bfd_elf32_bfd_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_free

此外,bfd/目录中的archures.cconfig.bfdMakefile.amtarget.c文件应该随着必要的 target-specific 更改进行更新。

opcodes

opcodes/目录应该至少有两个与目标相关的文件——一个用于汇编目标指令,另一个用于反汇编它们。文件名是:

  1. <target>-opc.c<target>-opc.h(头文件是可选的)
  2. <target>-dis.c<target>-dis.h(头文件是可选的)

<target>-dis.c文件包括打印反汇编指令的代码,以及用于适当匹配操作码和操作数的代码。
opcodes 目录中的configure.indisassemble.cMakefile.am文件也需要对其进行目标相关的更改。

include

include/目录包含针对特定目标的头文件,通常位于特定目标文件的子目录中。opcode信息通常保存在操作码子目录中的特定目标文件中。例如:

    include/elf/cr16.h
    include/opcode/cr16.h

binutils

该目录不需要任何新的目标特定文件。但configure.tgtMakefile.amreadelf.c文件应使用所需的任何目标特定信息进行更新。

gas

gas/config/子目录包含汇编器的特定目标文件。文件名是tc-<target>.ctc-<target>.h

上述文件应包括:

  • Sizes of (i.e., macros defines):
    • Registers
    • Instructions (i.e., maximum size)
    • Operands
  • Operand error types
  • Comment character used in assembly code
  • Comment character used in assembly code line
  • Line separator
  • Defining the target-specific
    • multi-character options, if any.
    • Process machine-dependent command line options in the md_parse_option function
    • Include machine-dependent usage-output in the md_show_usage function
  • A redefinition of the assemble directive using md_pseudo_table
  • Functions for getting registers along with type, size, and other information
  • md_begin function used to initialise/set-up all the tables, etc, that are machine-dependent items of the assembler
  • Parse functions:
    • parse_insn
    • parse_operands
    • parse_operand
  • Print functions:
    • print_insn
    • print_operand
    • print_operands
  • Print functions:
    • Function to assemble a single instruction assemble_insn
    • md_assemble is the first function called to assemble instruction
      在gas/目录本级,需要修改configure.tgt和Makefile.am文件以引用新文件,并添加对新目标的支持。

ld

scripttempl/<format><target>.sc中,定义架构的默认链接描述文件。
emulparams/<target><format>.em中,定义默认的仿真脚本文件。它包含自定义链接器行为所需的任何函数。
emulparams/<format><target>.sh中,定义可用于修改默认链接描述文件的任何参数。
ld/目录本级,需要更新configure.tgt文件以添加新的目标信息以及Makefile.am文件中新的目标信息构建规则。

构建和测试

构建 binutils 工具

构建 binutils 工具需要按照以下步骤操作:

  • 配置:使用目标和前缀选项运行配置脚本。例如:

      src/configure --target=cr16-elf --prefix=/local/cr16-bintuils
    

    其中,--target选项定义了要为其构建 binutils 工具的目标,--prefix选项是指定 binutils 工具安装目录的位置。

  • 构建:运行 make 为上述配置的目标构建 binutils 工具。例如:

     make all
     make install
    

    或者

     make all install
    

注意: 可以使用该选项make -jN通过使用主机 PC 上的所有处理器/CPU来快速构建工具。例如,如果你的主机 PC 有四个处理器,则可用make -j4快速构建。

测试 binutils 工具

可以使用 binutils 测试套件来测试上述构建的工具(如gasbinutlsld)。运行 binutils 测试套件需要安装DejaGNU软件包并设置 DejaGNU 环境变量。然后可以使用以下命令运行测试:

	make check

上面的命令能同时运行binutils,gasld测试套件。使用以下命令,可以分别运行binutilsgasld测试套件:

	make check-binutils 
	make check-gas 
	make check-ld

binutils 测试运行完成后,结果将总结于binutils/目录的binutils.sum文件中。binutils/binutils.log文件中还将提供更详细的信息。对于gas测试套件,结果位于gas/testsuite/gas.sumgas/testsuite/gas.log文件中,对于ld测试套件,结果位于ld/ld.sumld/ld.log文件中。

为了在主机和目标不同的环境中进行最全面的测试,DejaGNU 需要一些额外的配置。您可以通过设置 DejaGNU 环境变量来引用合适的配置文件,并在~/boards目录中定义自定义板配置文件来实现此目的。这些配置文件可用于指定合适的模拟器以及运行测试时如何连接它。

文档

一些 binutils 子目录又包含doc/子目录。这些文档以 texinfo 编写,可以将它们生成为 PDF、PostScript、HTML 或 info 文件。这些文档不是使用make allmake doc来自动构建的。创建文档需要改到单独的文档目录,并根据需要使用 make HTML make PDFmake psmake info。有意思的主要文件是:

  • bfd/doc/bfd.texinfo是BFD手册
  • binutils/doc/binutils.texi是 binutils 主要的用户指南
  • ld/ld.texinfo是链接器用户指南
  • gas/doc/as.texinfo是汇编程序用户指南

自动构建的例外是make install。 这将为binutils/doc/目录中的任一文档构建信息文件并将它们安装在install/目录的info/子目录中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值