How can I make GCC compile the .text section as writable in an ELF binary?

后端 未结 4 1620
我寻月下人不归
我寻月下人不归 2020-12-01 17:18

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

相关标签:
4条回答
  • 2020-12-01 17:44

    The easiest way i found (binutils 2.22) is to link with -N That can be passes to gcc with gcc -XN

    0 讨论(0)
  • 2020-12-01 17:49

    Try objcopy --writable-text on the compiled library, according to the documentation it should make .text writable.

    0 讨论(0)
  • 2020-12-01 18:01

    Probably the best approach is to use the system specific API to change the writability of the memory you wish to modify, modify it, then change it back.

    On unix family systems, you'd want to look at mprotect. Just keep in mind that it deals with blocks that are multiples of the page size of your system. Likely 4096, so rounding is likely required.

    0 讨论(0)
  • 2020-12-01 18:02

    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.

    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.

    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).

    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.

    0 讨论(0)
提交回复
热议问题