2015-06-11 13 views
5

Tôi đang cố gắng để tải một hàm thành một bộ nhớ đệm ánh xạ và gọi nó sau này vì vậy tôi đã thực hiện một trường hợp thử nghiệm để thử:sao chép chức năng hiện có vào bộ nhớ đệm

auto func() -> void{ 
    asm(
     "nop;" 
     "nop;" 
     "nop;" 
     "nop;" 
    ); 
} 

auto main(int argc, char *argv[]) -> int{ 
    void *exec_mem = mmap(nullptr, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 
    // check errors here 

    memcpy(exec_mem, reinterpret_cast<const void*>(func), 5); // size is known 
    (reinterpret_cast<void(*)()>(exec_mem))(); // function call 

    munmap(exec_mem, getpagesize()); 
} 

nào hoạt động tốt, nhưng ngay sau khi tôi cố gắng làm điều gì đó thậm chí tầm thường, tôi nhận được một segfault.

tôi đã cố gắng để làm một nhiệm vụ đơn giản biến như thế này:

int x; 
auto func() -> void{ 
    x = 5; 
} 

và bây giờ segfaults chức năng kêu gọi của Mẹ. Tôi đã thay đổi kích thước bộ đệm một cách thích hợp và chắc chắn rằng bộ nhớ chính xác đang được ghi vào bộ đệm.

Tôi thiếu thông tin quan trọng nào ở đây? Tại sao tôi không thể làm điều này?

P.S. Xin đừng dạy tôi về mã không an toàn, đây là một bài tập học tập cá nhân đơn giản.

+0

Bạn phải rất không an toàn trong công việc của mình ngay cả khi suy ngẫm viết loại mã này. –

+0

@EdHeal Vâng, tôi không lập trình cho một công việc. – CoffeeandCode

+1

Chỉ cần tò mò, cú pháp này là gì: 'auto/-> '? Chưa bao giờ thấy nó trước đây. –

Trả lời

4

Bỏ qua thực tế rằng đây là hành vi không xác định rõ ràng, nếu bạn gán một biến toàn cục, mã được tạo có khả năng sử dụng relative addressing để tham chiếu biến trên một số kiến ​​trúc.

Tức là, hàm mong đợi chính nó và x ở một địa chỉ cụ thể và nếu bạn di chuyển nó, mọi thứ sẽ bị hỏng.

Đây là những gì GCC của tôi tạo ra cho chức năng kiểm tra của bạn:

x: 
     .zero 4 
     .text 
     .globl _Z4funcv 
     .type _Z4funcv, @function 
_Z4funcv: 
.LFB2: 
     .cfi_startproc 
     pushq %rbp 
     .cfi_def_cfa_offset 16 
     .cfi_offset 6, -16 
     movq %rsp, %rbp 
     .cfi_def_cfa_register 6 
     movl $5, x(%rip) 
     nop 
     popq %rbp 
     .cfi_def_cfa 7, 8 
     ret 
     .cfi_endproc 

Lưu ý movl $5, x(%rip), có nghĩa là các mã sử dụng địa chỉ riêng của mình (được lưu trữ trong% rip) để tính toán vị trí của x và lưu trữ 5 trong đó.

Vì vậy, trong ngắn hạn, không có cách nào đơn giản để làm những gì bạn đang cố gắng làm, trừ khi bạn đảm bảo rằng chức năng của bạn chỉ có position-independent code. Và thậm chí sau đó, nó chỉ yêu cầu rắc rối.

+0

Bạn biết một cách để gây GCC để tạo ra mã độc lập vị trí cho một chức năng duy nhất? – CoffeeandCode

+1

@CoffeeandCode bạn có thể đặt các chức năng trong tập tin riêng của nó, và biên dịch các tập tin với -fPIC – tux3

+0

Có vẻ như một rắc rối, tôi sẽ nghỉ mát nếu tôi không tìm thấy gì. Cảm ơn câu trả lời :) Tôi hiểu những rủi ro liên quan, nhưng tôi cần những hành vi mong muốn và sẽ không sử dụng bất cứ điều gì như thế này trong bất kỳ dự án khác. – CoffeeandCode

Các vấn đề liên quan