2011-06-20 14 views
9

Aktualnie używam GCC 4.5.3, skompilowałem dla PowerPC 440 i kompiluję kod, który nie wymaga libc. Nie mam żadnych bezpośrednich wywołań memcpy(), ale kompilator wydaje się wstawiać jeden podczas kompilacji.Uzyskiwanie kompilacji GCC bez wstawiania wywołania memcpy

Istnieją opcje linkera, takie jak -nostdlib, -nostartfiles, -nodefaultlibs, ale nie mogę ich użyć, ponieważ nie wykonuję fazy łączenia. Ja tylko kompiluję. Z czymś takim:

$ powerpc-440-eabi-gcc -O2 -g -c -o output.o input.c 

Gdybym sprawdzić output.o z nm, widzę odniesienie do memcpy:

$ powerpc-440-eabi-nm output.o | grep memcpy 
    U memcpy 
$ 

Strona GCC mężczyzna wyjaśnia, w jaki sposób usunąć i połączenia do memcpy inne wywołania libc z łącznikiem, ale nie chcę, aby kompilator wstawiał je w pierwszej kolejności, ponieważ używam zupełnie innego łącznika (nie GNU ld i nie wie o libc).

Dziękujemy za pomoc.

+0

Jeżeli nic innego nie działa, bajt bajt po prosty Oparta na procesorze implementacja memcpy wystarczająca przynajmniej dla rzadko używanych przypadków jest prawdopodobnie krótsza niż większość odpowiedzi po Sted tutaj. –

Odpowiedz

5

Musisz wyłączyć tę optymalizację za pomocą -fno-builtin. Miałem ten problem raz podczas próby kompilowania memcpy dla biblioteki C. Nazwała się. Ups!

+1

Dzięki za odpowiedź! Po przeczytaniu instrukcji, wygląda na to, że -ofno-wbudowane lub -ffreestanding powinien zrobić dokładnie to, czego potrzebuję. Ale po dodaniu tych przełączników kompilatora nadal otrzymuję dwa odwołania do memcpy. Jakieś inne sugestie? – Brian

+0

@Brian: Znalazłem dokładnie ten sam problem. Czy to tylko błąd GCC? –

+0

Niestety, nie jest to poprawna odpowiedź: zdarzają się przypadki, gdy wywołania 'mem *' są nadal wstawiane, bez względu na wszystko. Zobacz odpowiedź Droopycoma, to jest prawdziwa! –

3

Można również dokonać binarny jest "wolnostojąca" jeden:

The ISO C Standard definiuje (w punkcie 4) dwie klasy zgodnej realizacji. Odpowiednia hostowana implementacja obsługuje cały standard [...]; zgodna wolnostojąca implementacja jest wymagana tylko w celu zapewnienia określonych udogodnień bibliotecznych: te w,,, i; od AMD1, także w; oraz w C99, także w i. [...].

Standard definiuje również dwa środowiska dla programów, środowisko wolnostojące, wymagane we wszystkich implementacjach i które może nie mieć zaplecza bibliotecznego poza wymaganymi wolnostojącymi implementacjami, w których obsługa uruchamiania i kończenia programu jest definiowana przez implementację, a środowisko hostowane, które nie jest wymagane, w którym zapewnione są wszystkie udogodnienia biblioteki, a uruchomienie odbywa się za pośrednictwem funkcji int main (void) lub int main (int, char * []).

Jądro systemu operacyjnego byłoby środowiskiem wolnostojącym; program korzystający z urządzeń systemu operacyjnego normalnie byłby w hostowanej implementacji.

(akapit dodany przeze mnie)

Więcej here. I odpowiednią opcję gcc/s (słowa kluczowe -freestanding lub -fno-builtin) można znaleźć here.

5

Gcc wysyła wezwanie do memcpy w niektórych okolicznościach, na przykład jeśli kopiujesz strukturę. Nie można zmienić zachowania GCC, ale można tego uniknąć, modyfikując kod, aby uniknąć takiej kopii. Najlepiej jest spojrzeć na zespół, aby dowiedzieć się, dlaczego gcc emitował memcpy i próbować go obejść. Będzie to jednak denerwujące, ponieważ zasadniczo musisz zrozumieć, jak działa gcc.

Wyciąg z http://gcc.gnu.org/onlinedocs/gcc/Standards.html:

Większość procedur wsparcia kompilatora GCC są stosowane przez obecne w libgcc, ale istnieje kilka wyjątków. GCC wymaga, aby wolne środowisko zapewniało memcpy, memmove, memset i memcmp.Na koniec, jeśli użyta zostanie funkcja __builtin_trap, a cel nie wdroży wzorca pułapki, wówczas GCC wyśle ​​wywołanie, aby przerwać.

+0

Zauważyliśmy, że gcc odwołuje się do memcpy kiedy zainicjowaliśmy lokalną tablicę: int x [4] = {1,2,3,4}; Przypuszczalnie gcc musiał skopiować te dane na lokalnym stosie za każdym razem, gdy weszliśmy w funkcję. Zatem zmiana go na statyczną definicję spowodowała, że ​​problem zniknął. static const int x [4] = {1,2,3,4}; – phord

+1

Tak, ale zmieniłeś również znaczenie kodu: tzn. Jeśli twoja funkcja zmienia x, to nie będzie {1,2,3,4} na początku następnego połączenia ... – Droopycom

+0

Prawidłowo, ale w takim przypadku obiecujemy, że nie zmienimy danych. Zapewniamy tę obietnicę, deklarując ją jako 'const int' array. I tak, moglibyśmy się zastrzelić, odrzucając const, ale bardzo poważnie podchodzimy do bezpieczeństwa broni i nie dbamy o taką głupotę. Pozostały problem może polegać na tym, że nasza tablica jest teraz w .data zamiast na lokalnym stosie. Ale to również nie stanowi problemu dla naszego użytkowania. YMMV. – phord

3

Nie ma potrzeby, aby -fno-builtins lub -ffreestanding ponieważ będą one niepotrzebnie wyłączyć wiele ważnych optymalizacje

To jest rzeczywiście „zoptymalizowane” przez drzewo-pętla-dystrybucja wzorców GCC, tak aby wyłączyć niechciane zachowanie zachowując użyteczna wbudowane funkcje, można po prostu użyć:

-fno-tree-loop-distribute-patterns

MUSL-libc wykorzystuje tę flagę na jej budowie i ma następującą notatkę w swoim skrypcie configure (Spojrzałem przez źródła i nie znaleźliśmy żadnych makr, więc powinny być wystarczająco)

# sprawdza opcje, które mogą być konieczne, aby zapobiec kompilatora z
# generującego wersje autoreferencyjna z memcpy ,, memmove, memcmp,
# i memset. Naprawdę, powinniśmy dodać sprawdza, czy to
# opcja jest wystarczająca, a jeśli nie, to dodać makra do sparaliżować te
# funkcje z lotnym ...
# tryflag CFLAGS_MEMOPS -fno-tree-pętla-rozprowadzać -patterns

można również dodać to jako atrybut do poszczególnych funkcji w gcc używając jego atrybut optymalizować tak, że inne funkcje mogą korzystać z wywołaniem mem*()

Powiązane problemy