c - 在 C 中实现数组绑定(bind)金丝雀

标签 c gcc memory embedded

我想在C程序(带有GCC,用于嵌入式)的数据布局中的战略位置上散布一些金丝雀,以用于检查是否有某个指针跑到野外。

类似于以下内容:

const volatile uint32_t canary_0 = CANARY_DEF;
static uint32_t some_global_array_0[SOME_SIZE_0] = {0};
const volatile uint32_t canary_1 = CANARY_DEF;
static uint32_t some_global_array_1[SOME_SIZE_1] = {0};
...

当然,我知道上面的示例不起作用,只是为了这个想法。当所有其他(例如通常的数组索引边界断言等)无法正确运行时,我想在安全关键型嵌入式软件中使用类似的东西作为后备的附加点。

我读到this post on the GCC mailing list (我害怕认为“工艺”应被解释为“飞机”......),建议使用结构。问题是,在更大的范围内,感觉它会严重扰乱程序结构,因此损失更多(开发人员拔头发并因此制造错误),而不是通过实现这样的故障安全机制来获胜。

目前我最好的选择是使用链接器脚本(就像实现堆栈金丝雀所必需的那样)将 RAM 分成不同的段,将金丝雀分散在中间。然而,这感觉有点脆弱,需要维护。 (或者也许不是这样?目前我对 LD 的链接器脚本知之甚少,仅足以了解基础知识,例如向微 Controller 使用的默认脚本添加代码闪存 CRC、堆栈金丝雀等。现在我什至缺乏知识如何制作灵活的布局以适应各节中分配的数据量)

就我的目的而言,考虑线程和弄乱某些操作系统的结构并不重要(因为在情况出现时实际上能够回退),因为在这里我们设计了没有第三方组件的单线程软件架构。如果主线程无法最终到达后备代码,那么看门狗就会杀死它。将这些内容包含在答案中是可以的,但请不要只是发布一个答案,指出由于 RTOS 出错而导致此类内容无法工作。

最佳答案

事实上,确保两个数据片段(几乎,直到对齐和填充)连续的唯一可靠方法是将它们放入单个聚合中(例如数组或struct)。否则允许编译器进行优化。

你可以考虑

volatile struct {
  uint32_t my1_canary_0 = CANARY_DEF;
  uint32_t my1_array_0[SOME_SIZE_0] = {0};
} my1;
#define canary0 my1.my1_canary_0
#define array0 my1.my1_array_0

所以我们使用的是结构体,但是上面的两个宏“隐藏”了它们!

但是,我不确定将整个struct声明为 volatile 是一个好主意 (也许只有金丝雀是不稳定的就足够了)。它可能会显着减慢您的代码速度。

重点是在哪里以及如何检查金丝雀?您可以手动执行此操作(但这很乏味),添加大量

assert (canary0 == CANARY_DEF);

在很多地方(或者你自己的类似断言的检查)。您还可以考虑使用 MELT 自定义 GCC出于此类目的 (例如,添加一个优化过程,该优化过程将在每个访问 array0 的 block 内添加上述代码的等效内容)。当然,这需要几周的工作。

正如我所评论的,最近 GCC 的 -fsanitize= 选项也应该很有帮助。

关于c - 在 C 中实现数组绑定(bind)金丝雀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27225306/

相关文章:

c# - 为什么 .net 程序在计算机有更多 ram 时使用更多 VirtualMemorySize64

c - 为什么这个 pangram 程序没有给出正确的答案?

c - 从函数 : Error 返回字符串指针

c++ - 如何在静态库中的单独 cpp 文件中链接未引用的变量?

c - 为什么 gcc -Wformat 不对 unsigned int 上的 printf %d 发出警告?

memory - I/O映射的I/O-端口地址是RAM的一部分

memory - 了解mmap

c - 关于strtok()的一些设置

c++ - C/C++ 最有效的 if 语句评估

gcc - GCC 是否有用于 AVX512 操作的内置函数?