2012-08-11 14 views
10

Zajmuję się udostępnianiem biblioteki, która może być wykonywana niezależnie, aby wydrukować własny numer wersji.Nie można wydrukowaćf liczby zmiennoprzecinkowe z wykonywalnej biblioteki współdzielonej

Mam zdefiniowano niestandardowy punkt wejścia jako:

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

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

i skompilować z

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

Ten kod kompiluje i biegnie doskonale.

Mój problem dotyczy zmiany parametru printf na float lub double (% f lub% lf). Biblioteka będzie następnie kompilować, ale segfault po uruchomieniu.

Ktoś ma jakieś pomysły?

Edit1:

Oto kod, który zwraca błąd:

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:

Dodatkowe informacje środowiskowe:

uname -a 

Linux mjolnir.site 3.1.10-1.16-desktop # 1 SMP PREEMPT śro 27 czerwca 2012 05:21:40 UTC (d016078) x86_64 x86_64 x86_64 GNU/Linux

gcc --version 

gcc (SUSE Linux) 4.6.2

/lib64/libc.so.6 

Skonfigurowano dla x86_64-suse-linux. Skompilowany przez GNU CC w wersji 4.6.2. Skompilowany w systemie Linux 3.1.0 w dniu 2012-03-30.

edit 3:

wyjścia w/var/log/messages upon segfault:

11 sierpnia jądro 08:27:45 Mjolnir: [+10560,068741] liblist.so [11222] ogólnym ochrona ip: 7fc2b3cb2314 sp: błąd 7fff4f5c7de8: 0 w bibliotece libc-2.14.1.so [7fc2b3c63000 + 187000]

+1

Działa to doskonale na mojej maszynie 32-bitowej. I powinno działać również na 64 bitach. czy podałeś i ? – TOC

+1

@ TOC Zrobiłem. Czy próbowałeś wydrukować liczbę zmiennoprzecinkową jako numer wersji? Kod, który wysłałem, działa dobrze, z wyjątkiem sytuacji, gdy drukujesz float. – kobrien

+0

Czy możesz pokazać kod, który drukuje float? –

Odpowiedz

5

Wyliczyłem to. :)

Operacje zmiennoprzecinkowe na x86_64 używają rejestrów wektorowych xmm. Dostęp do nich musi być wyrównany do granic 16-bitowych. To tłumaczy, dlaczego 32-bitowe platformy pozostały nienaruszone i działało drukowanie liczb całkowitych i znaków.

Mam skompilowane mój kod do montażu z:

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

następnie zmienione funkcję „my_main” będzie mieć więcej przestrzeni stosu.

Przed:

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 

Po:

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 

Potem skompilowany .S ten plik:

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

To rozwiązuje problem, ale będę przesłać ten wątek do Listy dyskusyjne GCC i GLIBC, ponieważ wygląda jak błąd.

Edit1:

Według noshadow w gcc IRC, to nie standardowy sposób to zrobić. Powiedział, że jeśli używa się opcji gcc -e, albo uruchom ręcznie środowisko wykonawcze C, albo nie używaj funkcji libc. Ma sens.

+0

ISTR, że istnieje opcja gcc do wyrównania stosu na większych granicach niż domyślny. Możesz go użyć do pracy, dopóki błąd nie zostanie naprawiony, zamiast modyfikować złożenie. – AProgrammer

+0

Brzmi nieźle. Alternatywnym sposobem jest nie używanie funkcji libc i używanie bezpośrednio syscalls, ale pamiętaj, że jest to więcej kodu i mniej przenośne. – kobrien

+1

Instrukcje ładowania pojedynczych wartości zmiennoprzecinkowych do rejestrów XMM nie wymagają wyrównania 16-bajtowego. Wymagają tylko czterobajtowego wyrównania dla pojedynczej precyzji i ośmiobajtowego wyrównania dla podwójnej precyzji. Możliwe, że napotkano inne problemy, takie jak naruszenie interfejsu binarnego aplikacji wymagającego wywołania podprogramów (niepoprawne wyrównanie stosu, może nie udało się ustawić bitu, który przekazuje parametry zmiennoprzecinkowe lub inne problemy). –

Powiązane problemy