GCC:如何告诉GCC将'main'函数放在.text节的开头?

15

我刚开始学习一些ARM编程,遇到了一个稍微有点烦人的问题。我正在使用Sourcery CodeBench Lite 2013.05-23(可以在此处找到:https://sourcery.mentor.com/GNUToolchain/release2449)来编译我的源代码。

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

是否有方法实现这一点?(也许通过链接脚本?)

谢谢

3个回答

19

问题已解决。对于遇到此问题的人:

  • 使用GCC编译时,在命令行中添加-ffunction-sections选项。这将告诉GCC将每个函数放在单独的节中。节名称的格式将为.text.#函数名#,不包括#(即如果函数属于.text节[默认情况下为真])。
  • 其次,使用链接器脚本将这些"函数节"排序到最终的大.text节中。例如,将main函数放在.text节的开头将导致一个LD脚本,看起来大致像这样:

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

7
你也可以使用:'int main(int argc, char **argv) attribute((section(".text.main")));',并将其余部分保留在默认文件段中。 - Goswin von Brederlow
如何将链接脚本传递给GCC?还是需要分两步完成?任何示例都会有所帮助。 - Brandon Ros
我认为,在链接器脚本中使用*(.text*.main);而不是*(.text.main);是更好和更通用的方式,因为在.text.main之间可能会有其他短语,就像在我的情况下,main标签是.text.startup.main,并且一开始并不能正常工作,后来通过在中间添加通配符进行修复。 - Celuk

5
首先,查看您的gcc默认链接脚本中如何定义.text section(因此您不必自己创建),方法是调用以下命令:
gcc -Wl,-verbose

这将打印默认的链接器脚本。我的显示如下,针对 .text 段:

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

因此,为了使“主”函数在.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

1
虽然这样做可以起作用,但是在所有其他函数中添加一个部分远非最简单的方法 - 请参阅已接受的答案以获取更简单的解决方案。 - mdma

2
您可以使用__attribute__将“main”放入自己的部分中:
int main (void) __attribute__ ((section ("entry")));

然后在 ld 文件中:

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

还有很多其他有趣的__属性__,在这里阅读更多相关信息:http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html


2
main 函数的正确返回类型是 int,而不是 void。(void main(void) 可能会被一些编译器允许;但在托管实现中,int main(void) 是通用的。) - Keith Thompson
3
这只是使用 __attributes__ 的一个例子,我不知道他的主函数是什么样子的 :) - ordahan
那么你应该选择 main 的两个有效签名之一。clang 拒绝编译 void main() - Peter Cordes
2
@PeterCordes:这不是唯一的两个有效签名。如果有人正在构建一个独立(非托管)环境(这可能是这个问题的情况 - 这是不清楚的),我希望CLANG在使用“-ffreestanding”编译时可以允许它。 - Michael Petch
1
@MichaelPetch:哦,好观点。是的,这适用于gcc和clang。https://godbolt.org/z/l5JGTu。(事实证明,gcc和clang现在在默认托管模式下拒绝`void main()`。我仍然认为这是一个很好的编辑,尽管这个特定的问题相当可能是关于独立代码的。) - Peter Cordes
@PeterCordes:完全不怀疑这个修改。最好使用两种都能工作的签名,所以我支持这个改变。我只是对有效签名做了一些观察。 - Michael Petch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接