2012-08-11 18 views
10

Estoy desarrollando una biblioteca compartida que se puede ejecutar de forma independiente para imprimir su propio número de versión.No se pueden imprimir los números de coma flotante de la biblioteca compartida ejecutable

he definido un punto de entrada personalizado como:

const char my_interp[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2"; 

void my_main() { 
    printf("VERSION: %d\n", 0); 
    _exit(0); 
} 

y compilo con

gcc -o list.os -c -g -Wall -fPIC list.c 
gcc -o liblist.so -g -Wl,-e,my_main -shared list.os -lc 

Este código compila y carreras perfectamente.

Mi problema es cuando cambio el parámetro de printf para que sea un flotante o doble (% f o% lf). La biblioteca compilará pero segfault cuando se ejecute.

¿Alguien tiene alguna idea?

edit1:

Aquí está el código que segfaults:

const char my_interp[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2"; 

void my_main() { 
    printf("VERSION: %f\n", 0.1f); 
    _exit(0); 
} 

Edit2:

detalles ambientales adicionales:

uname -a 

Linux mjolnir.site 3.1.10-1.16-escritorio # 1 SMP PREEMPT Mie Jun 27 de 2012 05:21:40 GMT (d016078) x86_64 x86_64 x86_64 GNU/Linux

gcc --version 

gcc (SUSE Linux) 4.6.2

/lib64/libc.so.6 

Configurado para x86_64-suse-linux. Compilado por GNU CC versión 4.6.2. Compilado en un sistema Linux 3.1.0 en 2012-03-30.

edición 3:

salida en/var/log/messages sobre violación de segmento:

Ago 11 08:27:45 mjolnir núcleo: [10560.068741] liblist.so [11222] generales ip de protección: 7fc2b3cb2314 sp: error 7fff4f5c7de8: 0 en libc-2.14.1.so [7fc2b3c63000 + 187000]

+1

Esto funciona perfectamente en mi máquina de 32 bits. Y debería funcionar en 64 bits también. ¿Incluyó y ? – TOC

+1

@TOC lo hice. ¿Intentó imprimir un número de coma flotante como el número de versión? El código que publiqué funciona bien, excepto cuando se imprime un flotador. – kobrien

+0

¿Puedes mostrar el código que imprime el flotador? –

Respuesta

5

Lo resolvió. :)

Las operaciones de punto flotante en x86_64 utilizan los registros vector xmm. El acceso a estos debe estar alineado en límites de 16 bytes. Esto explica por qué las plataformas de 32 bits no se vieron afectadas y la impresión de enteros y caracteres funcionó.

He compilado mi código para montaje con:

gcc -W list.c -o list.S -shared -Wl,-e,my_main -S -fPIC 

luego modificarse la función "my_main" ser tener más espacio de pila.

Antes:

my_main: 
.LFB6: 
.cfi_startproc 
pushq %rbp 
.cfi_def_cfa_offset 16 
.cfi_offset 6, -16 
movq %rsp, %rbp 
.cfi_def_cfa_register 6 
movl $.LC0, %eax 
movsd .LC1(%rip), %xmm0 
movq %rax, %rdi 
movl $1, %eax 
call printf 
movl $0, %edi 
call _exit 
.cfi_endproc 

Después:

my_main: 
.LFB6: 
.cfi_startproc 
pushq %rbp 
.cfi_def_cfa_offset 16 
.cfi_offset 6, -16 
subq $8, %rsp ;;;;;;;;;;;;;;; ADDED THIS LINE 
movq %rsp, %rbp 
.cfi_def_cfa_register 6 
movl $.LC0, %eax 
movsd .LC1(%rip), %xmm0 
movq %rax, %rdi 
movl $1, %eax 
call printf 
movl $0, %edi 
call _exit 
.cfi_endproc 

Entonces compilado esta .S archivo por:

gcc list.S -o liblist.so -Wl,-e,my_main -shared 

esto soluciona el problema, pero lo haré reenviar este hilo al Listas de correo de GCC y GLIBC, ya que parece un error.

edit1:

Según noshadow en IRC gcc, esta es una forma no estándar de hacer esto. Dijo que si se usa la opción gcc -e, se inicializa el tiempo de ejecución de C manualmente, o no se usan las funciones de libc. Tiene sentido.

+0

ISTR que hay una opción para gcc para alinear la pila en límites más grandes que la predeterminada. Podrías utilizarlo como una solución temporal hasta que se corrija el error en lugar de modificar el conjunto. – AProgrammer

+0

Suena bien. Otra forma es no usar funciones libc y usar syscalls directamente, pero tenga en cuenta que esto es más código y menos portátil. – kobrien

+1

Las instrucciones que cargan valores de coma flotante únicos en registros XMM no requieren alineación de 16 bytes. Solo requieren alineación de cuatro bytes para precisión simple y alineación de ocho bytes para precisión doble. Es posible que haya encontrado otros problemas, como la violación de la interfaz binaria de la aplicación, que requiere para ejecutar subrutinas (podría haber alineado incorrectamente la pila, haber fallado al establecer un bit que indica que se pasan parámetros de coma flotante u otros problemas). –

Cuestiones relacionadas