2009-12-18 9 views
14

¿Es de alguna manera posible detectar fallas de alineación de datos incluso en i386? Tal vez estableciendo un registro de máquina específica para i386 o algo así.x86: cómo detectar fallas de alineación de datos (también conocido como SIGBUS en sparc)

En Solaris-Sparc Estoy recibiendo un SIGBUS en este caso, pero en i386 todo está bien.

Medio Ambiente:

  • 32-bit de aplicación
  • Ubuntu Karmic
  • gcc/g ++ v4.4.1

EDITAR: Aquí es por eso que estoy pidiendo esto:

  • nuestra aplicación se bloquea en Sol-Sparc con SIGBUS. A los efectos de la depuración, trataría de obtener un comportamiento similar en nuestra plataforma i386.
  • nuestra máquina Sol-sparc es muy lenta, por lo que la compilación y la depuración llevan mucho tiempo allí. Y nuestra máquina i386 es increíblemente rápida (8 núcleos, 32G de memoria).
  • Incluso en las plataformas i386 hay un costo de rendimiento en las fallas de alineación de datos. Y, por lo tanto, me gustaría corregir las fallas de alineación de datos siempre que sea posible.
+0

Parece que ejecutar las pruebas en 'qemu' (que puede apuntar a SPARC) puede ser más rápido que si se ejecutara en un hardware real. – ephemient

+0

Nunca he probado qemu, pero eso parece interesante. ¿Funciona eso sin algún tipo de "ROM del sistema" o algo similar? –

+1

El proyecto QEMU agrupa 'openbios-sparc', que es suficiente para permitir que' qemu-system-sparc' sea una máquina real. También hay 'qemu-sparc' que ejecuta solo un ejecutable Linux bajo emulación, traduciendo syscalls al kernel nativo. – ephemient

Respuesta

3

Para ampliar la respuesta de Vokuhila-Oliba mirando el hilo "SOF Mis-aligned pointers on x86.", parece que gcc puede generar código con acceso a memoria mal alineado. AFAIK no tienes ningún control sobre esto.

Habilitar las comprobaciones de alineación en el código compilado de gcc sería una mala idea. Se arriesga a obtener errores de SIGBUS para el código bueno C.

reeditado: Lo siento

+0

@alexandre: I * quiero * obtener estos errores SIGBUS. No en el código de producción, por supuesto, pero solo para la depuración. –

+3

Corre el riesgo de tener SIGBUS para el código que __work en SPARC__. Parece que x86 gcc no permite el acceso alineado en lugares como la inicialización de variables y no estoy seguro de que pueda cambiar ese comportamiento. –

+0

@alexandre: ¡tienes razón!Mi propia segunda respuesta muestra cómo verificar las fallas de alineación en i386. Pero este código funciona perfectamente bien en Sparc. En i386, recibe SIGBUS. El comportamiento de GCC para i386 se puede cambiar utilizando, p. atributo __ ((alineado (sizeof (char *)))). Pero no es posible hacerlo globalmente estableciendo un indicador global de GCC. Solo las configuraciones __attribute individuales en un elemento de datos son posibles. Y eso es demasiado esfuerzo para el proyecto en el que estoy trabajando :-( –

0

Intel incorporó transferencias desalineadas desde el principio: era uno de los puntos de venta cuando x86 era completamente nuevo. Entiendo tus razones para querer atrapar el acceso no alineado, pero no creo que sea posible.

Edit: muy contento de haber demostrado estar equivocado.

+0

no está completamente equivocado. Aunque SIGBUS puede forzarse incluso en i386, no ayuda mucho. Eso se debe a que en el SPARC una "mala alineación de la pila" no se considera dañina y no causa un SIGBUS. Pero en i386 causa SIBGUS incluso para una "alineación errónea de pila" inofensiva cuando se establece el indicador de CA. –

7

Mientras tanto, encontré un documento de la CPU Intel que aborda este tema.

Ver Intel® 64 and IA-32 Architectures Software Developer’s Manual.

Parece ser difícil juntar todas estas cosas. Sin embargo, no parece que sea completamente imposible. El capítulo interesante es 4.10.5 Comprobación de la alineación

EDITAR (un poco de material condensado del citado documento):

página 5-60

Interrupt 17 Alignment Check Exception (#AC) 

to enable alignment checking, the following conditions must be true: 

AM flag is set(bit 18 of control regisster CR0) 
AC flag is set (bit 18 of the EFLAGS) 
The CPL is 3 (protected mode or virtual-8086 mode). 

adicionalmente - en 14.8.2.6 - Se mencionan los errores del controlador de memoria. No sé si es lo mismo solo en otras palabras:

table 14-11, Encoding of MMM and CCCC Sub-Fields 
Address/Command Error AC 011 
+0

Desafortunadamente, todos los códigos de modo de usuario se ejecutan en el anillo 3; lo anterior no generará excepciones. – ephemient

+0

Me falta conocimiento sobre estos "anillos" de CPU. Pero si un programa normal utiliza el anillo 3, sería lo suficientemente bueno. –

+0

Lo siento, lo leí antes; "El procesador no genera excepciones de alineación cuando se opera en el nivel de privilegio 0, 1 o 2", definitivamente deja el anillo 3 a la vista. – ephemient

3

¡He encontrado una solución muy simple en SOF! Ver: Mis-aligned pointers on x86.

int main(int argc, char **argv) 
{ 
# if defined i386 
    /* EDIT: enable AC check */ 
    asm("pushf; " 
    "orl $(1<<18), (%esp); " 
    "popf;"); 
# endif 

    char d[] = "12345678"; /* yep! - causes SIGBUS even on Linux-i386 */ 
    return 0; 
} 

Pero debo confesar que no entiendo por qué la asignación

carbón d [] = "12345678";

se supone que está mal alineada?

EDIT:

en la máquina SPARC no hay SIGBUS en la línea de la asignación a Char d [].

2

Intel son muy grandes en el apoyo a las cargas no alineados. Si tuviera que detectar tales cargas en una plataforma Intel, creo que tendría que modificar valgrind para tratar las cargas desalineadas como errores. Tal modificación no es trivial, pero valgrind se diseñó con la idea en mente de que los usuarios podían crear nuevas 'herramientas'. Creo que una simple modificación de la herramienta memcheck detectaría sus referencias desalineadas. Y el informe de errores es realmente muy bueno.

0

Muchos años después: si tu gcc/clang es lo suficientemente nuevo (GCC 4.9, clang 3.3?), Puedes construir tu código con el desinfectante de comportamiento indefinido (-fsanitize=undefined) para recibir advertencias sobre accesos desalineados en una plataforma determinada (pero tenga en cuenta que las diferentes plataformas tienen diferentes requisitos de alineación, diferentes compiladores elegirán diferentes diseños, etc.). Vea https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html y https://developers.redhat.com/blog/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/ para más detalles.

Cuestiones relacionadas