He escrito un programa "peligroso" en C++ que salta de un marco de pila a otro. El objetivo es pasar del nivel más bajo de la pila de llamadas a la persona que llama, hacer algo y luego volver a saltar hacia abajo, omitiendo todas las llamadas entremedio.¿Qué hace el registro PIC (% ebx)?
Lo hago cambiando manualmente la dirección base de la pila (configuración %ebp
) y saltando a una dirección de etiqueta. Funciona totalmente, con gcc e icc ambos, sin ningún tipo de corrupción en la pila. El día en que esto funcionó fue un día genial.
Ahora tomo el mismo programa y lo vuelvo a escribir en C, y no funciona. Específicamente, no funciona con gcc v4.0.1 (Mac OS). Una vez que salto al nuevo marco de la pila (con el puntero de la base de la pila establecido correctamente), se ejecutan las siguientes instrucciones, justo antes de una llamada al fprintf
. La última instrucción que aparece aquí se estrella, eliminación de referencias a NULL:
lea 0x18b8(%ebx), %eax
mov (%eax), %eax
mov (%eax), %eax
He hecho algunas depuración, y he descubierto que al establecer el registro %ebx
manualmente cuando cambio de marcos de pila (usando un valor observé antes de salir la función en primer lugar), soluciono el error. He leído que este registro trata sobre el "código independiente de posición" en gcc.
¿Qué es el código de posición independiente? ¿Cómo funciona el código de posición independiente? ¿A qué apunta este registro?
Puede considerar setjmp/longjmp para obtener esta funcionalidad sin necesidad de eliminar% ebx directamente. –
En general, sí, tienes razón. En este caso, necesito poder saltar a la persona que llama, ejecutar alguna otra función y luego volver a bajar al destinatario. Con setjmp/longjmp, la otra función sobrescribirá la pila del llamado. –