2010-04-06 21 views
6

Estoy experimentando y me gustaría poder ver lo que se guarda en la pila durante una llamada al sistema (el estado guardado del proceso de aterrizaje del usuario). De acuerdo con http://lxr.linux.no/#linux+v2.6.30.1/arch/x86/kernel/entry_32.S, muestra que los diversos valores de registros se guardan en esos desplazamientos particulares al puntero de pila. Aquí está el código que he estado tratando de utilizar para examinar lo que se guarda en la pila (esto es, en una llamada al sistema a medida que he creado):¿Cómo se determinan los valores guardados en la pila?

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

donde el valor es un entero largo sin signo.

A partir de ahora, este valor no es el esperado (se muestra un 0 se guarda para el valor de usuario de ds).

¿Estoy accediendo correctamente al desplazamiento del puntero de la pila?

Otra posibilidad podría ser ¿podría usar un depurador como GDB para examinar el contenido de la pila mientras estoy en el kernel? No tengo mucho uso extensivo con la depuración y no estoy seguro de cómo depurar código dentro del kernel. Cualquier ayuda es muy apreciada.

Respuesta

0

Tenga en cuenta que el código x86_64 a menudo pasará valores en los registros (ya que tiene tantos) por lo que no habrá nada en la pila. Compruebe la salida intermedia de gcc (-S IIRC) y busque push en el conjunto.

No estoy familiarizado con la depuración del código del kernel, pero gdb es definitivamente mejor para examinar la pila de forma interactiva.

4

El montaje en línea es más complicado de lo que parece. Tratando de cubrir en breve las preocupaciones por GCC:

  1. Si modifica los registros del procesador, es necesario poner estos registros en la lista de clobber. Es importante tener en cuenta que la lista de clobber debe contener TODOS los registros que haya cambiado directamente (lea explícitamente) o indirectamente (lea implícitamente);
  2. Para reforzar (1), las operaciones condicionales y matemáticas también cambian los registros, más conocidos como indicadores de estado (cero, acarreo, desbordamiento, etc.), por lo que debe informarlo agregando "cc" a la lista clobber;
  3. Agregue "memoria" si modifica posiciones de memoria diferentes (lectura aleatoria);
  4. Agregue la palabra clave volátil si modifica la memoria que no se menciona en los argumentos de entrada/salida;

A continuación, el código se convierte en:

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

El argumento de salida no está obligado a estar en la lista clobber porque GCC ya sabe que será cambiado.

alternativa, puesto que todo lo que quiere es el valor del registro ESP, puede evitar todo el dolor de hacer esto:

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

Podría no resuelve su problema, pero es el camino a seguir. Como referencia, marque this, this y this.

5

No es necesario ensamblar en línea. El estado guardado que entry_32.S coloca en la pila para una llamada al sistema se presenta como un struct pt_regs, y se puede obtener un puntero a ella como esta (que tendrá que incluir <asm/ptrace.h> y/o <asm/processor.h> ya sea directa o indirectamente):

struct pt_regs *regs = task_pt_regs(current);

Cuestiones relacionadas