2015-06-11 12 views
5

Ich versuche, eine Funktion in einen zugeordneten Speicherpuffer zu laden und später anrufen, also habe ich einen Testfall gemacht auszuprobieren:Kopieren vorhandene Funktion in dem Speicherpuffer

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()); 
} 

die gut arbeitet, aber Sobald ich etwas Triviales versuche, bekomme ich einen Segfault.

Ich habe versucht, eine einfache variable Zuordnung wie dies zu tun:

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

und jetzt segfaults meinen Funktionsaufruf. Ich habe die Puffergröße entsprechend geändert und bin sicher, dass der richtige Speicher in den Puffer geschrieben wird.

Welche wichtige Information fehlt mir hier? Warum kann ich das nicht tun?

P.S. Bitte lehre mich nicht über unsicheren Code, dies ist eine einfache persönliche Lernübung.

+0

Sie müssen in Ihrem Job sehr unsicher sein, auch wenn Sie daran denken, diese Art von Code zu schreiben. –

+0

@EdHeal Ja, ich programmiere nicht für einen Job. – CoffeeandCode

+1

Nur neugierig, was ist das für eine Syntax: 'auto/-> '? Habe es noch nie gesehen. –

Antwort

4

Wenn Sie die Tatsache ignorieren, dass dies ein eklatantes undefiniertes Verhalten ist, wird der generierte Code bei der Zuweisung einer globalen Variablen wahrscheinlich relative addressing verwenden, um die Variable auf einigen Architekturen zu referenzieren.

Das heißt, die Funktion erwartet sich selbst und x an einer bestimmten Adresse, und wenn Sie es verschieben, brechen die Dinge. Diese

ist, was mein GCC für Ihre Testfunktion erzeugt:

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 

Notiere die movl $5, x(%rip), was bedeutet, dass der Code seine eigene Adresse verwendet (in% rip gespeichert), um die Position von x und Speicher 5 zu berechnen drin.

Kurz gesagt, es gibt keine einfache Möglichkeit, das zu tun, was Sie versuchen, es sei denn, Sie stellen sicher, dass Ihre Funktion nur position-independent code hat. Und selbst dann fragt es nur nach Ärger.

+0

Sie wissen, wie GCC positionsunabhängigen Code für eine einzelne Funktion erzeugen kann? – CoffeeandCode

+1

@CoffeeandCode Sie könnten die Funktion in eine eigene Datei setzen, und kompilieren Sie die Datei mit -fPIC – tux3

+0

Scheint wie ein Streit, ich werde darauf zurückgreifen, wenn ich nichts finde. Danke für die Antwort :) Ich verstehe die Risiken, aber ich brauche das gewünschte Verhalten und würde so etwas in keinem anderen Projekt verwenden. – CoffeeandCode

Verwandte Themen