将CRC存储到AXF/ELF文件中

将CRC存储到AXF/ELF文件中,c,gcc,arm,crc,lpc,C,Gcc,Arm,Crc,Lpc,我目前正在Windows 7上的工具链中开发一个C程序,这是一个面向NXP Cortex M3微处理器的带有gcc的IDE。它提供了一种通过JTAG编译微处理器链接程序的简单方法。生成的结果是由调试配置加载的AXF文件(ELF格式) 加载的程序驻留在0x00000到0x3FFFB的闪存中。我希望在0x3FFFC中包含一个4字节CRC-32,以便在启动时验证程序。我添加了另一个部分,并使用gcc\uuuuuuuuuuu属性指令访问该内存位置 uint32_t crc32_build __attri

我目前正在Windows 7上的工具链中开发一个C程序,这是一个面向NXP Cortex M3微处理器的带有gcc的IDE。它提供了一种通过JTAG编译微处理器链接程序的简单方法。生成的结果是由调试配置加载的AXF文件(ELF格式)

加载的程序驻留在0x00000到0x3FFFB的闪存中。我希望在0x3FFFC中包含一个4字节CRC-32,以便在启动时验证程序。我添加了另一个部分,并使用gcc
\uuuuuuuuuuu属性
指令访问该内存位置

uint32_t crc32_build __attribute__ ((section(".text_MFlashCRC")));
为了计算和存储CRC-32值,我的计划是使用以下构建后步骤:

arm-none-eabi-size "${BuildArtifactFileName}"
arm-none-eabi-objcopy -O binary "${BuildArtifactFileName}" "${BuildArtifactFileBaseName}.bin"
checksum -p ${TargetChip} -d "${BuildArtifactFileBaseName}.bin"
../util/srec_cat "${BuildArtifactFileBaseName}.bin" -binary -crop 0 0x3FFFC -fill 0xFF 0x00000 0x3FFFC -crc32-b-e 0x3FFFC -o "${BuildArtifactFileBaseName}.crc.bin" -binary
echo ""
echo "CRC32:"
../util/srec_cat "${BuildArtifactFileBaseName}.crc.bin" -binary -crop 0x3FFFC 0x40000 -o - -hex-dump
这将创建一个带有校验和的二进制文件(对于引导加载程序是必需的),然后在使用的闪存上计算CRC,并将CRC值存储在0x3FFFC

但是,我认为我无法使用调试器加载二进制文件。有一个内置的编程实用程序与LPCXpresso,可以加载修改后的二进制文件,但是,这不允许我调试。我相信我可以尝试使用“仅附加”模式启动原始AXF文件的调试会话,但是,这会变得很麻烦

我已经能够使用readelf检查AXF文件中的
crc32\u build
变量。有没有办法编辑AXF文件中的变量?是否有一种行业标准的方法来插入CRC作为构建后步骤?

据我所知,没有行业标准。有多种技术可以做到这一点。我建议您使用
crc32_build
作为'C'中的
extern
,并通过链接器脚本定义它。比如说,

  $ cat ld.script
  .text : {
    _start_crc_region = .;
    *(.text);
    crc32_build = .;
    LONG(CALC_CRC);
    _end_crc_region = .;
  }
 $ ld --defsym=CALC_CRC=0 -T ld.script *.o -o phony.elf
 $ objcopy -j sections phony.elf -o phony.bin # sections means checksum 'areas'
 $ ld --defsym=CALC_CRC=`crc32 phony.bin` -T ld.script *.o -o target.elf
第一次调用将值
CALC_CRC
作为零传递,然后使用设置的值重新链接。比如说,

  $ cat ld.script
  .text : {
    _start_crc_region = .;
    *(.text);
    crc32_build = .;
    LONG(CALC_CRC);
    _end_crc_region = .;
  }
 $ ld --defsym=CALC_CRC=0 -T ld.script *.o -o phony.elf
 $ objcopy -j sections phony.elf -o phony.bin # sections means checksum 'areas'
 $ ld --defsym=CALC_CRC=`crc32 phony.bin` -T ld.script *.o -o target.elf
我使用这种技术向图像添加数字签名;它应该同样适用于crc值。链接器脚本允许您定位变量,这对于CRC之类的完整性检查通常很重要,但对于简单的校验和则无关紧要。链接器脚本还允许您为区域的开始和结束定义符号。没有剧本,你需要一些精灵的自省

当然,您可以扩展这个想法,以包括init数据和其他分配的部分。在某些时候,您需要使用
objcopy
来提取节,并在构建时进行完整性检查。这些部分可能有各种对齐约束,在进行构建时crc计算时,您需要在主机上模拟这些约束(在上面的phony.bin中)

另外,当您生成一个srec文件时,一切都已经完成了


如果您在使用
--defsym
时遇到问题,您可以使用sed、awk、perl、python等预处理ld.script,并在CALC_CRC所在的位置用十六进制值替换文本。

这似乎是一个不错的方法。我必须弄清楚如何在对LPCXpresso工具链中断最小的情况下使用它,因为它已经自动生成链接器脚本。如果我理解正确,我还需要修改makefile,用定义CALC_CRC的命令替换它们的
ld
命令?是的,这是正确的。你可能必须改变使任何方式,因为你需要做两个链接。第一个具有虚拟/零CRC。第二个将实际填充CRC。
ld-r
(部分链接)也可能有用。然而,我使用了上述方法,但我的问题是确定最终尺寸,因为这已包含在证书中(实际上,您可以使用
\u end\u crc\u region-\u start\u crc\u region
获得相同的结果。在计算构建crc时,您可能必须减去最终的crc大小;即,不要在虚拟图像中包含零。您可以对crc输入部分使用
\u属性部分
,但您必须使用自定义链接器脚本并将输入在某个输出部分中的节(因为不存在标准)。因此,该方法将为您提供相同的最终解决方案(在我看来),您还可以在链接器脚本中定义空间。您的代码需要知道大小(在图像中编译)如果CRC调用代码是CRC调用的,或者,你可以把它放在某个预先确定的最大大小上,但是这会浪费运行时间。如果我也想把这个扩展到.DATA部分,LD脚本可以被配置成保持CRC值在数据的末尾吗?我已经在那里遇到了一个问题,因为它应该是const,通常是PAR。t of.text,so在.data之前映射。除了在所有.text上运行CRC,跳过CRC位置,然后继续.data之外,还有其他方法吗?
objcopy-j.text-j.data
将复制这两个部分。但是,运行时CRC必须跳转指针,因此我只需存储两个CRC值并分别计算它们。I d在一个值中同时执行这两项操作,您认为不会有多大收获吗?
const
是一个“C”结构。对于链接器,
.data
来自初始数据值“initdata”。此部分在启动时复制到最终的
.data
地址。因此,在更改任何“C”全局/静态数据之前,必须运行数据的CRC;或者您可以为某些输入文件定义一些特殊的
.data
,而不只是CRC it.Asm或C。