Frage

Ich bin den Aufbau eines Programms, das mprotect () verwendet, um einen Block von Speicher zu beschränken den Zugriff. Wenn der Speicher angefordert wird, wird ein SIGSEGV geworfen, die ich für die Verwendung eines Signals () mithören.

Sobald die SIGSEGV erkannt wurden, muß ich den Zeiger auf den Speicher irgendwie zuzugreifen, die angefordert wurde (das wirft er den Fehler) und die Größe des Segments angefordert. Ist das möglich?

void fifoSigHandler(){

    // Needs to only remove protection from requested block of virtual memory
    mprotect(fifoVm,(size_t)fifoVm_size,PROT_WRITE);
    printf("Caught Seg Fault");
}

void fifo_init(void* vm, int vm_size, int n_frames, int page_size)
{
    fifoVm = vm;
    fifoVm_size = vm_size;
    fifoFrames = n_frames;
    fifoPageSize = page_size;

    mprotect(fifoVm,(size_t)fifoVm_size,PROT_NONE);

    signal(SIGSEGV, fifoSigHandler);
}

Darüber hinaus ist es eine Möglichkeit, die Höhe der mprotect () ein Speicherblock zu bestimmen aktuell zugeordnet ist (PROT_NONE, PROT_READ, etc ..)?

War es hilfreich?

Lösung

Sie haben sigaction mit SA_SIGINFO zu verwenden, anstatt signal Handler zu etablieren, und dann werden Sie wieder mit nützlichen Informationen in einem siginfo_t aufgerufen, darunter si_addr.

si_addr, erklärt wie in sigaction (2), wird die Adresse enthalten. Was die Länge, gut, du bist kein Glück, wenn Sie bereit sind, Anweisungen zu analysieren. Beste, was Sie tun können, ist take action für die Seite in si_addr berichtet, und dann, wenn das nicht genug ist, werden Sie ein anderes Signal schnell genug bekommen. Zumindest das ist, wie wir haben die Dinge in Objektspeicher.

Andere Tipps

Sie suchen libsigsegv http://libsigsegv.sourceforge.net/

Aber Vorsicht, dass mprotect Aufruf ist nur Signal sicher in Linux, anderen POSIX-Systeme können dies nicht unterstützen.

Ich fürchte, dass in Linux die einzige Möglichkeit, Speicherschutz-Bits zu erhalten, ist in /proc/$pid/meminfo lesen

Auf einer seitlichen Anmerkung (nur Linux): Wenn Sie über den Speicherverbrauch besorgt und beabsichtigen Seiten einer größeren Abbildung eines aktivieren, indem man dann würde ich Ihre Mapping mmap mit MAP_NORESERVE in diesem Fall raten erstellen Sie eine bekommen Mapping auf Null gefüllten copy-on-write-Seiten, die physikalische RAM auf dem ersten Schreib zuteilen wird. MAP_NORESERVE weist den Kernel nicht Ihr Gedächtnis mit Swap-Speicher sichern so dass Sie 64 TB virtuellen Adressraum zuweisen oben. Einziger Nachteil ist, dass, wenn Sie genügend Speicherplatz sichern! Schreckliche Dinge passieren können (OOM-Killer).

Schritt 1: : Init ein sigaction:

struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
sigemptyset(&act.sa_mask);
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;

Schritt 2 : Nehmen Sie diese sigaction Griff SIGSEGV:

sigaction(SIGSEGV, &act, NULL);

(Optional) Schritt 3: : Machen Sie es andere Speichersignale verarbeiten zu:

sigaction(SIGBUS, &act, NULL);
sigaction(SIGTRAP, &act, NULL);

Fügen Sie Fehlerbehandlung als notwendig

Schritt 4: : Definieren Sie die Handler-Funktion:

void handler(int signal, siginfo_t* siginfo, void* uap) {
    printf("Attempt to access memory at address %p\n", 
           siginfo->si_addr);
    #ifdef LINUX_64BIT
    printf("Instruction pointer: %p\n",
           (((ucontext_t*)uap)->uc_mcontext.gregs[16]));
    #elif LINUX_32BIT
    printf("Instruction pointer: %p\n",
           (((ucontext_t*)uap)->uc_mcontext.gregs[14]));
    #endif
}

Sie können beziehen sich auf die man-Seiten für ucontext_t und siginfo_t für interessantere Daten Handler extrahieren können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top