对于下面的答案,我将使用这个测试程序:
#include <stdio.h>
#include <stdlib.h>
int
main (int argc, char **argv)
{
printf ("Hello world\n");
void *m = main;
*((char *) m) = 0;
exit (0);
}
编译:
$ gcc -g -o test test.c
如预期:
$ gdb test
...
(gdb) run
Starting program: /home/amb/so/test
Hello world
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a2 in main (argc=1, argv=0x7fffffffe628) at test.c:9
9 *((char *)m) = 0;
(gdb)
这里明显的路线是使用-Wl 标志到gcc 将-N 或(又名--omagic)传递给链接器,即gcc ... -Wl,--omagic ...,尽管这可能会产生其他不良结果(例如禁用共享库)。从手册页:
-N
--omagic
Set the text and data sections to be readable and writable. Also, do not page-align the
data segment, and disable linking against shared libraries. If the output format
supports Unix style magic numbers, mark the output as "OMAGIC". Note: Although a
writable text section is allowed for PE-COFF targets, it does not conform to the format
specification published by Microsoft.
让我们试一试:
$ gcc --static -g -Wl,--omagic -o test test.c
$ ./test
Hello world
$
这很好用,但是您失去了对动态库的支持。
要保持动态库支持,并保留可写文本段,您应该能够使用:
objcopy --writable-text ...
来自手册页:
--writable-text
Mark the output text as writable. This option isn't meaningful for all object file
formats.
这应该可以,但不会,objdump 会验证。因此,这是一个比--writable-text 更进一步的解决方案,正如 OP 在 cmets 中所说的那样,它似乎并没有像 tin^Wmanpage 上所说的那样做。
让我们看看这些部分是如何标记的:
$ gcc -g -o test test.
$ objdump -h test | fgrep -A1 .text
12 .text 00000192 0000000000400490 0000000000400490 00000490 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
现在让我们摆脱 READONLY 标志:
$ objcopy --set-section-flags .text=contents,alloc,load,code test test1
$ objdump -h test1 | fgrep -A1 .text
12 .text 00000192 0000000000400490 0000000000400490 00000490 2**4
CONTENTS, ALLOC, LOAD, CODE
现在READONLY 已按要求离开了。
但是:
$ gdb test1
...
(gdb) run
Starting program: /home/amb/so/test1
Hello world
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a2 in main (argc=1, argv=0x7fffffffe628) at test.c:9
9 *((char *)m) = 0;
(gdb)
我怀疑这里的问题是 ELF 部分名称以外的其他内容在实际加载时使该部分成为只读。这可能就是人们建议您使用mprotect 的原因。很抱歉没有得到更多帮助。