【问题标题】:GCC: how to tell GCC to put the 'main' function at the start of the .text section?GCC:如何告诉 GCC 将“main”函数放在 .text 部分的开头?
【发布时间】:2013-10-28 12:53:24
【问题描述】:

我刚开始学习一些 ARM 编程,但遇到了一个有点烦人的问题。我用来编译源代码的工具链是 Sourcery CodeBench Lite 2013.05-23(可以在这里找到:https://sourcery.mentor.com/GNUToolchain/release2449

我需要告诉 GCC 或 LD 或 OBJCOPY 将“main”函数的已编译字节码放在 .text 部分的开头。

有什么方法可以实现吗? (也许通过链接器脚本?)

谢谢

【问题讨论】:

    标签: gcc main ld linker-scripts objcopy


    【解决方案1】:

    解决了这个问题。对于面对它的人:

    • 使用 GCC 编译时,在命令行中添加 -ffunction-sections 选项。这将告诉 GCC 将每个函数放在一个单独的部分中。部分名称的格式将为 .text.#function name#,不带 #(即,如果函数属于 .text 部分 [默认情况下是真的])。
    • 其次,使用链接描述文件将这些“函数部分”排序到最后的大 .text 部分。例如,将 ma​​in 函数放在 .text 部分的开头会导致 LD 脚本大致如下所示:

      ENTRY(main)
      SECTIONS
      {
          .text :
          {
              *(.text.main);
              *(.text*);
          }
      }
      

    【讨论】:

    • 你也可以使用:'int main(int argc, char **argv) __attribute__((section(".text.main")));'并将其余部分保留在默认部分中。
    • 如何将链接描述文件传递给 GCC?还是分两步完成?任何例子都会有所帮助。
    【解决方案2】:

    首先,查看 gcc 的默认链接器脚本中的 .text 部分是如何定义的(因此您不必自己制作),将其称为:

    gcc -Wl,-verbose
    

    这将打印出默认的链接描述文件。我的 .text 部分显示了这个:

    /* text: Program code section */
      .text : 
      {
        *(.text)
        *(.text.*)
        *(.gnu.linkonce.t.*)
      }
    

    因此,为了让“main”函数成为 .text 部分中的第一个(其余部分是连续的),您必须为 所有其他函数设置“section”属性。例如:

    void main(void);
    void funct1(....) __attribute__ ((section (".text.A")));
    void funct2(....) __attribute__ ((section (".text.A")));
    void funct3(....) __attribute__ ((section (".text.A")));
    

    “归因”函数原型就足够了。这样,当您现在编译时,“main”函数将是“.text”部分中的第一个函数,所有其他函数将紧随其后。

    如果您想将“.text”部分(即“main”函数)放在特定地址(例如 0x1000),请记住链接:

    gcc .... -Wl,-Ttext=0x1000
    

    【讨论】:

    • 虽然这可行,但向所有其他函数添加一个部分远非最简单的方法 - 请参阅接受的答案以获得更简单的解决方案。
    【解决方案3】:

    您也可以使用__attribute__ 将“main”放在自己的部分中:

    int main (void) __attribute__ ((section ("entry")));
    

    然后在ld文件中:

    ENTRY(main)
    SECTIONS
    {
        .text :
        {
            *(main)
            *(.text)
        }
    }
    

    还有很多其他有趣的__attributes__,在这里阅读更多关于它们的信息:http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

    【讨论】:

    • main 的正确返回类型是 int,而不是 void。 (void main(void) 可能被某些编译器允许;int main(void) 对于托管实现是通用的。)
    • 只是使用__attributes__ 的一个例子-不知道他的主要是什么样子:)
    • 那么您应该选择main 的两个有效签名之一。 clang 拒绝编译void main().
    • @PeterCordes :这些不是唯一的 2 个有效签名。如果有人在独立(非托管)环境中构建(这个问题可能就是这种情况 - 不清楚)。如果使用-ffreestanding,我希望 CLANG 允许它编译
    • @MichaelPetch:哦,好点。是的,gcc 和 clang 就是这种情况。 godbolt.org/z/l5JGTu。 (结果 gcc 和 clang 都拒绝 void main() 现在处于默认托管模式。我仍然认为这是一个很好的编辑,尽管这个特殊问题很可能是关于独立代码的。
    猜你喜欢
    • 1970-01-01
    • 2010-12-01
    • 2015-05-19
    • 2012-05-28
    • 2020-10-17
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多