在运行时处理重定位

时间:2013-07-28 18:10:34

标签: compiler-construction linker x86 code-analysis jit

我正在尝试构建一个基本的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编译代码无济于事。

0 个答案:

没有答案