【发布时间】:2015-02-11 13:48:42
【问题描述】:
如果你曾经用 gcc 链接过内核,你可能知道参数 -lgcc。 这个参数重要吗?它有什么作用 ?
【问题讨论】:
如果你曾经用 gcc 链接过内核,你可能知道参数 -lgcc。 这个参数重要吗?它有什么作用 ?
【问题讨论】:
如果你做一些驱动程序/内核开发,你可以使用-nostdlib 从臃肿的标准库中删除你的模块。但是,您还删除了 GCC 的所有内部 hack,以便在整个硬件范围内保持一致的行为。
http://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Link-Options.html
-nostdlib
链接时不要使用标准的系统启动文件或库。没有启动文件,只有您指定的库将是 传递给链接器,指定系统链接的选项 库,例如 -static-libgcc 或 -shared-libgcc,将被忽略。 编译器可以生成对 memcmp、memset、memcpy 和 memmove 的调用。 这些条目通常由 libc 中的条目解析。这些条目 积分应通过其他机制提供,当这 选项已指定。
-nostdlib 和 -nodefaultlibs 绕过的标准库之一是 libgcc.a,它是 GCC 用来克服特定机器的缺点或特殊需求的内部子例程库 对于某些语言。 (有关更多信息,请参阅与 GCC 输出的接口 libgcc.a 的讨论。)在大多数情况下,您需要 libgcc.a,即使 您想避免使用其他标准库。换句话说,当你 指定 -nostdlib 或 -nodefaultlibs 你通常应该指定 -lgcc 也是。这可确保您没有未解决的引用 内部 GCC 库子例程。 (例如,`__main',用于 确保将调用 C++ 构造函数;见collect2。)
https://gcc.gnu.org/onlinedocs/gcc-4.6.1/gccint/Interface.html#Interface
3 与 GCC 输出接口
GCC 通常配置为使用相同的函数调用约定 通常在目标系统上使用。这是通过 描述的机器描述宏(请参阅目标宏)。
但是,结构和联合值的返回方式不同 在一些目标机器上。因此,使用 PCC 编译的函数 不能从使用 GCC 编译的代码中调用返回此类类型,并且 反之亦然。这通常不会引起麻烦,因为很少有 Unix 库 例程返回结构或联合。
GCC 代码返回 1、2、4 或 8 个字节的结构和联合 long 在用于 int 或 double 返回值的相同寄存器中。 (海合会 通常也会在寄存器中分配此类类型的变量。) 其他大小的结构和联合通过将它们存储到 调用者传递的地址(通常在寄存器中)。目标 hook TARGET_STRUCT_VALUE_RTX 告诉 GCC 将这个地址传递到哪里。
相比之下,大多数目标机器上的 PCC 返回结构和联合 通过将数据复制到静态存储区域中的任意大小,以及 然后返回该存储的地址,就好像它是一个指针 价值。调用者必须将数据从该内存区域复制到 需要价值的地方。这比使用的方法慢 由 GCC 提供,并且无法重入。
在某些目标机器上,例如 RISC 机器和 80386, 标准系统约定是将地址传递给子程序 在哪里返回值。在这些机器上,已经配置了 GCC 使用此方法时,要与标准编译器兼容。 它可能不兼容 1、2、4 或 8 字节的结构。
GCC 使用系统的标准约定来传递参数。上 一些机器,前几个参数在寄存器中传递;在 其他的,都在堆栈上传递。可以使用 注册在任何机器上传递的参数,这可能 导致显着的加速。但结果将是完整的 与遵循标准约定的代码不兼容。所以 仅当您切换到 GCC 作为唯一时,此更改才实用 系统的 C 编译器。我们可以实现寄存器参数传递 一旦我们有一个完整的 GNU 系统,我们就可以在某些机器上 用 GCC 编译库。
在某些机器(尤其是 SPARC)上,某些类型的参数 “通过不可见的引用”传递。这意味着该值为 存储在内存中,并将内存位置的地址传递给 子程序。
如果您使用 longjmp,请注意自动变量。 ISO C 说 未声明为 volatile 的自动变量未定义 longjmp 后的值。这就是 GCC 承诺要做的所有事情,因为它 很难正确恢复寄存器变量,并且其中之一 GCC 的特点是它可以将变量放入寄存器中,而无需您的 要求它。
【讨论】: