2010-04-06 7 views
6

Sto facendo qualche esperimento e vorrei poter vedere cosa viene salvato nello stack durante una chiamata di sistema (lo stato salvato del processo di terra dell'utente). Secondo lo http://lxr.linux.no/#linux+v2.6.30.1/arch/x86/kernel/entry_32.S, mostra che i vari valori dei registri vengono salvati in corrispondenza di quegli offset specifici per il puntatore dello stack. Ecco il codice che ho cercato di utilizzare per esaminare ciò che viene salvato nello stack (questo è in una chiamata di sistema personalizzato che ho creato):Come determinare i valori salvati nello stack?

asm("movl 0x1C(%esp), %ecx"); 
asm("movl %%ecx, %0" : "=r" (value)); 

cui valore è un unsigned long.

A partire da ora, questo valore non è quello previsto (viene visualizzato uno 0 viene salvato per il valore utente di ds).

Sto accedendo correttamente all'offset del puntatore stack?

Un'altra possibilità potrebbe essere possibile utilizzare un debugger come GDB per esaminare il contenuto dello stack mentre si trova nel kernel? Non ho un uso molto esteso con il debug e non sono sicuro di come eseguire il debug del codice all'interno del kernel. Ogni aiuto è molto apprezzato.

risposta

0

Ricordare che il codice x86_64 spesso trasmette i valori nei registri (poiché ne ha così tanti), quindi nulla sarà in pila. Controllare l'uscita intermedia gcc (-S IIRC) e cercare push nell'assieme.

Non ho familiarità con il debug del codice del kernel, ma gdb è decisamente più bello esaminare lo stack in modo interattivo.

4

L'assemblaggio in linea è più complicato di quanto sembri. Cercando di coprire a breve le preoccupazioni per GCC:

  1. Se modifica i registri del processore, è necessario mettere questi registri nella lista dei clobber. È importante notare che l'elenco dei clobber deve contenere i registri ALL modificati direttamente (leggi esplicitamente) o indirettamente (leggi implicitamente);
  2. Per rinforzare (1), le operazioni condizionali e matematiche modificano anche i registri, più noti come flag di stato (zero, carry, overflow, ecc.), Quindi è necessario informarlo aggiungendo "cc" all'elenco dei clobber;
  3. Aggiungi "memoria" se modifica diverse posizioni di memoria (lette a caso);
  4. Aggiungere la parola chiave volatile se modifica la memoria che non è menzionata negli argomenti di input/output;

Poi, il codice diventa:

asm("movl 0x1C(%%esp), %0;" 
    : "=r" (value) 
    : /* no inputs :) */ 
    /* no modified registers */ 
); 

L'argomento di uscita non è richiesto di essere sulla lista clobber perché GCC sa già che sarà cambiato.

In alternativa, dal momento che tutto quello che volete è il valore del registro ESP, è possibile evitare tutto il dolore facendo questo:

register int esp asm("esp"); 
esp += 0x1C; 

Non potrebbe risolvere il tuo problema, ma è la strada da percorrere. Per riferimento, selezionare this, this e this.

5

Nessuna necessità di montaggio in linea. Lo stato salvato che entry_32.S spinge in pila per una chiamata di sistema è strutturato come un struct pt_regs, e si può ottenere un puntatore ad esso come questo (avrete bisogno di includere <asm/ptrace.h> e/o <asm/processor.h> direttamente o indirettamente):

struct pt_regs *regs = task_pt_regs(current);