为什么用-fno-pic编译Android内核模块?

jck*_*ter 5 android kernel kernel-module linux-kernel

我经常读到Android内核模块必须编译-fno-pic才能工作.这是针对ARM体系结构的,还是为什么不需要/(什么时候)x86的内核模块需要使用该标志进行编译?

Ale*_*idt 3

根据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,在 AArch64 上为 28k,在 m68k 和 RS/6000 上为 32k。x86 没有这样的限制。) 位置无关代码需要特殊支持,因此仅适用于某些机器。对于 x86,GCC 支持 System V 的 PIC,但不支持 Sun 386i。为 IBM RS/6000 生成的代码始终与位置无关。

当设置该标志时,宏__pic____PIC__被定义为 1。

So-fno-pic的意思是“不要使用位置无关代码 (PIC)”。

但为什么?

好吧,通过查看https://developer.arm.com/products/software-development-tools/hpc/documentation/note-about-building-position-independent-code-pic-on-aarch64,我们发现:

在 AArch64 上使用 -fpic 编译器标志和 GCC 编译器会导致编译器在代码中的每个地址计算中生成更少的指令,并且可以提供代码大小和性能优势。但是,它还为全局偏移表 (GOT) 设置了 32k 的限制,并且由于 GOT 溢出,构建可能会在可执行链接阶段失败。

因此,最终,这似乎-fno-pic更多是一种预防措施,而不是真正的需要。当然,这只是一个猜测,可能还涉及更多的事情。