如何让 GCC 将 .text 部分编译为可写在 ELF 二进制文件中? [英] How can I make GCC compile the .text section as writable in an ELF binary?

查看:22
本文介绍了如何让 GCC 将 .text 部分编译为可写在 ELF 二进制文件中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to be able to dynamically change the executable code within a library I am using. Essentially, I would like to dynamically NOP out certain functions if they are not needed.

但是,我使用的库的 .text 部分是不可写的(大多数程序都是这种情况).我有库的源代码,因此想使用 GCC 将其编译为可写的.

However, the .text section of the library I am using is not-writable (as is the case for most programs). I have the source code of the library and so would like to use GCC to compile it as writable.

有没有办法做到这一点?

Is there a way to do this?

推荐答案

在一般意义上,mprotectsys/mman.h<下的首选选择(在符合 POSIX 的系统上)/code>(检查 http://linux.die.net/man/2/mprotect).只需获取进程可执行部分的地址和系统页数,然后调用 mprotect 请求权限;写信给它;然后,再次调用mprotect释放写权限.

In the general sense, mprotect is the perferred choice (on POSIX conforming systems) under sys/mman.h (check http://linux.die.net/man/2/mprotect). Simply get the address and system page count of the executable section of your process and call mprotect to request permission permissions; write to it; then, call mprotect again to release write permission.

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

However, if this is meant to be on low-level routines where speed is of absolute importance (or mprotect is not available) then you'll want to compile the library with its .text section writable as calling mprotect most likely issues a Translation Lookaside Buffer (TLB) flush that (especially in a multi-processor environment) can and will cause a bottleneck. If the specific system is using hardware protection via paging (which nearly all are now) then the only way to change the protection is by doing a TLB flush which must be executed on every referenced page, referenced page table (group of pages), referenced page directory (group of page tables) and every processor. To top it off, this must be executed in ring 0 which requires a syscall which just puts the cherry on top for overhead.

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

In the latter case, the easiest solution would be to compile the library normally and then objcopy it with --writable-text (as mentioned by ggiroux).

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

Another solution would be to define the linker map file linker.ld yourself. Then you may specify permissions of any section explicitly. Its not too complicated; if system-dependent. Refer to documentation at http://www.math.utah.edu/docs/info/ld_3.html. You could also look at your system provided linker.ld file and modify it from there. Passing -Wl,--verbose to gcc will instruct the linker to spit out all relevant files (including its default linker.ld) in which you could then modify the permissions of the .text section and recompile the library (forevermore) using the new linker.ld file.

总而言之,我的建议是按照最后一段所述进行操作,并使用稍微修改的链接器脚本编译您的库.

To summarize, my recommendation would be to do as the last paragraph states and compile your library with a slightly modified linker script.

这篇关于如何让 GCC 将 .text 部分编译为可写在 ELF 二进制文件中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆