0

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ても役に立ちません。

4

0 に答える 0