【问题标题】:Maximum stack size needed for a C program on MSP430MSP430 上的 C 程序所需的最大堆栈大小
【发布时间】:2013-03-22 09:48:16
【问题描述】:

在不使用递归的 C 程序中,理论上应该可以计算出调用给定函数以及它调用的任何函数所需的最大/最坏情况堆栈大小。是否有任何免费的开源工具可以做到这一点,无论是来自源代码还是编译的 ELF 文件?

或者,有没有办法从 ELF 文件中提取函数的堆栈帧大小,以便我可以尝试手动解决?

我正在使用 MSPGCC 3.2.3 为 MSP430 进行编译(我知道它是旧版本,但在这种情况下我必须使用它)。要分配的堆栈空间是在源代码中设置的,并且应该尽可能小,以便剩余的内存可以用于其他事情。我已经读到您需要考虑中断使用的堆栈空间,但我正在使用的系统已经考虑到这一点 - 我正在尝试计算在此之上添加多少额外空间。另外,我读过函数指针使这变得困难。在此处使用函数指针的少数地方,我知道它们可以调用哪些函数,因此如果已知被调用函数和调用函数所需的堆栈空间,则可以手动考虑这些情况。

静态分析似乎是比运行时堆栈绘制更强大的选项,但如果没有好的静态方法可以在运行时解决它是一个选项。

编辑:

我找到了 GCC 的 -fstack-usage 标志,它在编译时保存了每个函数的帧大小。不幸的是,MSPGCC 不支持它。但它对于尝试在不同平台上做类似事情的人来说可能很有用。

【问题讨论】:

  • 这真的是解决您问题的方法吗?我总是对堆栈相当慷慨,并用堆栈金丝雀保护它以确保它完好无损。我认为这种方法的主要问题是它可能会在以后引起麻烦。例如,当您需要使用 24 位 PC 而不是 16 位(现在只是一般的 8 位体验)来获得更大的程序内存时,或者您只需要一些额外的功能,最好通过一些额外的调用层来实现。然后一个精确设置的堆栈可能真的会回到你身上。当然,如果您要挤出最后一点,那好吧,但我认为这确实应该是最后一点。
  • “是否有任何免费的开源工具可以做到这一点”。有一个免费版本的(非开源)IAR IDE(30 天或 4K 代码限制),其中链接器列表选项生成应用程序的堆栈使用情况。即使您使用的是 GCC,为了获取堆栈大小(每个函数的总和)、代码大小(每个函数的总和)以及内存位置、变量地址和大小等其他详细信息,您也可以使用 IAR嵌入式工作台。

标签: c stack elf msp430


【解决方案1】:

有趣的问题。

我希望这些信息在调试版本中包含的调试数据中静态可用。

我简要了解了DWARF 标准,它确实为称为DW_AT_frame_baseDW_AT_static_link 的函数指定了两个属性,可用于“计算帧 子程序相关实例的基础 立即包含子例程或入口点”。

【讨论】:

  • 谢谢。我不确定它们有多大用处,但我确实在 DWARF 规范中遇到了“调用框架信息”,看起来它可能有更多信息。现在我只需要让 GCC 生成 .debug_frame 部分 - -gdwarf-2 -g3 不会这样做。
【解决方案2】:

我认为唯一要做的就是通过静态分析。您需要考虑所有非静态局部变量的空间,这些变量主要是指针,但无论如何都将存储在堆栈中的指针,您还需要为当前运行地址保留空间调用者,因为它将由编译器存储在堆栈中,因此可以在函数返回后将控制权返回给调用者,而且,所有函数参数都需要空间。 基于此,如果你有一个工具能够计算所有参数、自动变量并计算它们的大小,你应该能够计算出你需要的最小堆栈帧大小。 请注意,编译器还可能会尝试为您的特定架构对齐堆栈上的值,这可能会使堆栈空间需求比您从该计算中所期望的要大一些。

【讨论】:

    【解决方案3】:

    一些嵌入式 IDE 可以在运行时提供有关堆栈使用情况的信息 我知道 IAR 嵌入式工作台支持它。

    请注意,您需要考虑到中断是异步发生的,因此请采用最大的堆栈使用场景并为其添加中断上下文。如果像 ARM 处理器一样支持嵌套中断,您也需要考虑到这一点。

    【讨论】:

      【解决方案4】:

      虽然静态分析是确定最大堆栈使用量的最佳方法,但您可能不得不求助于实验方法。此方法不能保证您获得绝对最大值,但可以让您很好地了解堆栈的使用情况。

      您可以检查链接描述文件以获取 __STACK_END 和 __STACK_SIZE 的位置。您可以使用它们以易于识别的模式(如 0xDEAD 或 0xAA55)填充堆栈空间。通过酷刑测试运行您的代码,以确保生成尽可能多的中断。

      测试后,您可以检查堆栈空间,看看有多少堆栈被覆盖。

      【讨论】:

      • 您甚至可以将它们声明为外部。 extern char __STACK_END; &__STACK_END 将是堆栈中最后一个字节的地址
      【解决方案5】:

      TinyOS 在堆栈大小分析方面做了一些工作。这里描述: http://tinyos.stanford.edu/tinyos-wiki/index.php/Stack_Analysis

      他们只支持AVR,但说“MSP430不难支持,但这不是超高优先级”。无论如何,该页面提供了大量资源。

      【讨论】:

        猜你喜欢
        • 2015-02-13
        • 2010-12-22
        • 2011-07-27
        • 1970-01-01
        • 2011-01-29
        • 1970-01-01
        • 2013-09-26
        • 1970-01-01
        相关资源
        最近更新 更多