JIT
目的を理解するために基本的なエンジンを構築しようとしています。
私が読んだ基本的な概念のいくつかを実行しようとすると、次の例があります。
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
void * fptr;
int (*_printf)(const char*,...);
int test1(void)
{
int arr[100] = {0x0};
_printf("In %s\n", __FUNCTION__); << Segfault due to this printf call
return 5;
}
int main()
{
fptr = mmap(NULL, 4096, PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0);
memset((unsigned char *)fptr, 0x90, 4096);
printf("Address of printf = %p\n", &printf);
_printf = printf;
int (* testptr)(void);
memcpy(fptr, (unsigned char *)&test1, 67);
testptr = fptr;
int i = test1();
printf("ret = %d\n", i);
i = 0x0;
i = testptr();
printf("ret = %d\n", i);
return 0;
}
この例では、関数 test1() を別の実行可能メモリにコピーし、それを実行しようとします (67 バイトをコピーしていますが、これは粗雑ですが、この例では問題になりません)。
共有ライブラリ (つまり、この場合は printf) から外部シンボルを呼び出さない場合、コピーされた関数を実行できますが、test1() から printf() が呼び出されると、プログラムは SIGSEGV に直面します。
これは、相対アドレスが使用されているために発生していると思います。つまり、元の場所から実行された場合に test1() が機能し、そうでない場合はすべての相対アドレスが無効になります。
これがgdbの言うことです、
info registers
r15 0x0 0
rip 0x7ffff7ff7025 0x7ffff7ff7025
eflags 0x10202 [ IF RF ]
cs 0x33 51
(gdb) x/10bx $rip
0x7ffff7ff7022: 0xf3 0x48 0xab 0x48 0x8b 0x15 0x08 0x0a
0x7ffff7ff702a: 0x20 0x00
(gdb)
gdb) x/67bx fptr
0x7ffff7ff7000: 0x55 0x48 0x89 0xe5 0x48 0x81 0xec 0x90
0x7ffff7ff7008: 0x01 0x00 0x00 0xcc 0x8d 0xb5 0x70 0xfe
0x7ffff7ff7010: 0xff 0xff 0xb8 0x00 0x00 0x00 0x00 0xba
0x7ffff7ff7018: 0x32 0x00 0x00 0x00 0x48 0x89 0xf7 0x48
0x7ffff7ff7020: 0x89 0xd1 0xf3 0x48 0xab 0x48 0x8b 0x15
0x7ffff7ff7028: 0x08 0x0a 0x20 0x00 0xbe 0x1d 0x08 0x40
0x7ffff7ff7030: 0x00 0xbf 0xf4 0x07 0x40 0x00 0xb8 0x00
0x7ffff7ff7038: 0x00 0x00 0x00 0xff 0xd2 0xb8 0x05 0x00
0x7ffff7ff7040: 0x00 0x00 0xc9
(gdb)
And here is the test1() function, code is compiled with -O0
(gdb) disassemble/r test1
Dump of assembler code for function test1:
0x000000000040062c <+0>: 55 push %rbp
0x000000000040062d <+1>: 48 89 e5 mov %rsp,%rbp
0x0000000000400630 <+4>: 48 81 ec 90 01 00 00 sub $0x190,%rsp
0x0000000000400637 <+11>: 48 8d b5 70 fe ff ff lea -0x190(%rbp),%rsi
0x000000000040063e <+18>: b8 00 00 00 00 mov $0x0,%eax
0x0000000000400643 <+23>: ba 32 00 00 00 mov $0x32,%edx
0x0000000000400648 <+28>: 48 89 f7 mov %rsi,%rdi
0x000000000040064b <+31>: 48 89 d1 mov %rdx,%rcx
0x000000000040064e <+34>: f3 48 ab rep stos %rax,%es:(%rdi)
0x0000000000400651 <+37>: 48 8b 15 08 0a 20 00 mov 0x200a08(%rip),%rdx # 0x601060 <_printf>
0x0000000000400658 <+44>: be 1d 08 40 00 mov $0x40081d,%esi
0x000000000040065d <+49>: bf f4 07 40 00 mov $0x4007f4,%edi
0x0000000000400662 <+54>: b8 00 00 00 00 mov $0x0,%eax
0x0000000000400667 <+59>: ff d2 callq *%rdx
0x0000000000400669 <+61>: b8 05 00 00 00 mov $0x5,%eax
0x000000000040066e <+66>: c9 leaveq
0x000000000040066f <+67>: c3 retq
End of assembler dump.
この問題を解決する方法について何か考えはありますか?
でコードをコンパイルし-fPIC -pie
ても役に立ちません。