【发布时间】:2015-02-03 03:54:42
【问题描述】:
我经常读到 Android 内核模块必须使用 -fno-pic 编译才能工作。这是否特定于 ARM 架构,或者为什么不需要/(何时)x86 的内核模块需要使用该标志进行编译?
【问题讨论】:
-
这篇文章会明确说明:-stackoverflow.com/questions/11614441/…
标签: android linux-kernel kernel kernel-module
我经常读到 Android 内核模块必须使用 -fno-pic 编译才能工作。这是否特定于 ARM 架构,或者为什么不需要/(何时)x86 的内核模块需要使用该标志进行编译?
【问题讨论】:
标签: android linux-kernel kernel kernel-module
根据https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Code-Gen-Options.html,-fno-pic是-fpic参数的否定形式。来自同一链接:
-fpic 如果目标机器支持,则生成适合在共享库中使用的与位置无关的代码 (PIC)。这样的代码 通过全局偏移表 (GOT) 访问所有常量地址。 动态加载程序在程序启动时解析 GOT 条目 (动态加载器不是 GCC 的一部分;它是操作的一部分 系统)。如果链接的可执行文件的 GOT 大小超过 机器特定的最大大小,您会从 指示 -fpic 不起作用的链接器;在这种情况下,重新编译 用 -fPIC 代替。 (这些最大值在 SPARC 上为 8k,在 SPARC 上为 28k m68k 和 RS/6000 上的 AArch64 和 32k。 x86 没有这样的限制。) 与位置无关的代码需要特殊支持,因此 仅适用于某些机器。 对于 x86,GCC 支持 PIC for System V,但不适用于 Sun 386i。为 IBM RS/6000 生成的代码 始终与位置无关。
设置此标志时,宏
__pic__和__PIC__被定义为 1.
所以-fno-pic 的意思是“不要不使用与位置无关的代码 (PIC)。”
但是为什么呢?
在 AArch64 上对 GCC 编译器使用 -fpic 编译器标志会导致 编译器在每个地址计算中生成少一条指令 代码,并且可以提供代码大小和性能优势。然而, 它还为全局偏移表 (GOT) 设置了 32k 的限制,并且 构建可能在可执行链接阶段失败,因为 GOT 溢出。
所以,最后,-fno-pic 似乎更像是一种预防措施,而不是真正的需要。当然,这只是一种猜测,可能涉及更多的事情。
【讨论】: