最近正在试图把 CanoKey 的闭源版本从 Arm Keil 工具链切换到开源的 GNU 工具链。这过程中有许多波折,或许之后会有独立的博客讲述这个故事。在迁移初期就遇到的一大问题是,Canokey 的安全芯片使用的处理器是大端的 SC000,本质上是基于 Armv6-M 架构的 Cortex-M0,使用 Thumb 指令集。而 Arm 官方提供的 Arm GNU Toolchain 对于这一架构仅有小端支持(即 host triple 为 arm-none-eabi
,而非 armeb-none-eabi
)。
虽然小端的 GCC 使用支持 -mbig-endian
来切换端序,但其携带的所有标准库都是小端的。如对于 Cortex-M0,其 multilib ABI 为 thumb/v6-m/nofp
,在解压后的工具链的 arm-none-eabi/lib/thumb/v6-m/nofp
目录下即可找到 libc
、libgcc
、libm
等比较关键的标准库(尤其是 libgcc
,即使替换其他 C 标准库,也同样会依赖它)。由于这些库都是跟随 GCC 一同编译的,并且 multilib 中不存在端序标识,因此比较简单的方案是重新编译整个工具链,以获得完整的大端支持。
一番搜索后,我在 GitHub 找到了 armeb-none-eabi-gcc-buildpatch 项目,它提供了对 Arm 官方编译脚本的 patch(但已经无法在新版的 GCC 上使用了),甚至在 release 中提供了编译好的 GCC 8.3.1。但目前 GCC 都已经 11.2 了,当然要自己动手了。一番尝试后,得到步骤如下:
- 从上面给的 Arm GNU Toolchain 页面下载源码(当前名为
gcc-arm-src-snapshot-11.2-2022.02.tar.xz
),解压并进入目录。 - 运行
./install-sources.sh
,获得工具链源码(如有必要,可替换src/gcc
等目录为更新的版本,但不保证成功编译)。 - 给
build-common.sh
和build-toolchain.sh
打补丁,主要是修改所有的默认 host triple 和configure
选项为大端。具体 patch 内容由于太长,我上传到了 Gist。 - 编译依赖项:
./build-prerequisites.sh --skip_steps=howto,mingw,mingw32,package_sources
。 - 编译工具链:
./build-toolchain.sh --skip_steps=gdb-with-python,howto,manual,mingw,mingw32,mingw-gdb-with-python,mingw32-gdb-with-python,package_sources
。
在经过漫长的等待后(真的很慢,因为有非常多的 multilib
要编译——如果愿意的话,大概可以进一步 patch,关掉不需要的部分),在 pkg
目录下就能找到名称以 gcc-armeb-none-eabi-
开头的工具链包;如果没有跳过 package_sources
,则还有一份源码。这样得到的工具链就是我所需要的,其中包含了 newlib
、newlib-nano
的大端版本。