如何让GCC将.text段编译为ELF二进制文件中的可写?

时间:2012-01-09 20:12:56

标签: c++ gcc elf

我希望能够动态更改我正在使用的库中的可执行代码。从本质上讲,如果不需要,我想动态地删除某些功能。

但是,我使用的库的.text部分是不可写的(大多数程序都是如此)。我有库的源代码,因此希望使用GCC将其编译为可写。

有办法做到这一点吗?

4 个答案:

答案 0 :(得分:9)

在一般意义上,mprotectsys/mman.hmprotect(检查http://linux.die.net/man/2/mprotect)的优先选择(在POSIX符合系统上)。只需获取流程可执行部分的地址和系统页数,然后调用mprotect即可获得权限许可;写信给它;然后,再次调用mprotect以释放写入权限。

但是,如果这是针对速度极为重要的低级例程(或.text不可用),那么您将需要使用其mprotect部分编译库可写为调用objcopy最有可能发出翻译后备缓冲区(TLB)刷新(特别是在多处理器环境中)可能并将导致瓶颈。如果特定系统通过分页使用硬件保护(几乎所有都是现在),则更改保护的唯一方法是执行TLB刷新,必须在每个引用的页面上执行,引用的页面表(页面组),引用页面目录(页表组)和每个处理器。最重要的是,这必须在环0中执行,这需要一个系统调用,只需将樱桃放在顶部以便开销。

在后一种情况下,最简单的解决方案是正常编译库,然后用--writable-text编译linker.ld(如ggiroux所述)。

另一种解决方案是自己定义链接器映射文件linker.ld。然后,您可以明确指定任何部分的权限。它不太复杂;如果系统依赖。请参阅http://www.math.utah.edu/docs/info/ld_3.html处的文档。您还可以查看系统提供的-Wl,--verbose文件并从那里进行修改。将linker.ld传递给gcc将指示链接器吐出所有相关文件(包括其默认的linker.ld),然后您可以在其中修改.text部分的权限并使用new {重新编译库(永远) {1}}档案。

总而言之,我的建议是按照最后一段所述进行操作,并使用略微修改的链接描述文件编译您的库。

答案 1 :(得分:6)

在已编译的库上尝试objcopy --writable-text,根据它应该生成的文档.text可写。

答案 2 :(得分:2)

我找到的最简单的方法(binutils 2.22)是与-N链接 这可以通过gcc -XN传递给gcc

答案 3 :(得分:1)

最好的方法可能是使用特定于系统的API来更改您想要修改的内存的可写性,修改它,然后再将其更改回来。

在unix系列系统上,您需要查看mprotect。请记住,它处理的是您系统页面大小的倍数的块。可能是4096,所以可能需要进行四舍五入。